[ld2410] Add frame header synchronization to readline_()

Add frame header validation to prevent the parser from getting stuck
in an overflow loop when it loses sync with the UART byte stream
(e.g. after module restart or UART noise). This is the same latent
bug fixed in ld2450 (PR #14135) and present in ld2420.

The fix validates the first 4 bytes of each frame match a known
header (DATA or CMD) before accumulating data. On header byte
mismatch, the buffer resets and checks if the mismatched byte starts
a new frame. Also adds a return after buffer overflow reset to
prevent immediately re-accumulating the overflowed byte.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jonathan Swoboda
2026-02-19 21:56:46 -05:00
parent c1265a9490
commit e9aeb42e2b

View File

@@ -601,15 +601,33 @@ void LD2410Component::readline_(int readch) {
return; // No data available
}
// Frame header synchronization: verify first 4 bytes match a known frame header.
// This prevents the parser from getting stuck in an overflow loop after losing sync
// (e.g. after module restart or UART noise).
if (this->buffer_pos_ < HEADER_FOOTER_SIZE) {
const uint8_t byte = static_cast<uint8_t>(readch);
// Verify header bytes match the frame type established by byte 0
if (this->buffer_pos_ > 0) {
const uint8_t *expected = (this->buffer_data_[0] == DATA_FRAME_HEADER[0]) ? DATA_FRAME_HEADER : CMD_FRAME_HEADER;
if (byte != expected[this->buffer_pos_]) {
this->buffer_pos_ = 0; // Reset and fall through to check if this byte starts a new frame
}
}
// First byte must match start of a data or command frame header
if (this->buffer_pos_ == 0 && byte != DATA_FRAME_HEADER[0] && byte != CMD_FRAME_HEADER[0]) {
return;
}
}
if (this->buffer_pos_ < MAX_LINE_LENGTH - 1) {
this->buffer_data_[this->buffer_pos_++] = readch;
this->buffer_data_[this->buffer_pos_] = 0;
} else {
// We should never get here, but just in case...
ESP_LOGW(TAG, "Max command length exceeded; ignoring");
this->buffer_pos_ = 0;
return;
}
if (this->buffer_pos_ < 4) {
if (this->buffer_pos_ < HEADER_FOOTER_SIZE) {
return; // Not enough data to process yet
}
if (ld2410::validate_header_footer(DATA_FRAME_FOOTER, &this->buffer_data_[this->buffer_pos_ - 4])) {