From 05cc1687a51cbb9e18e62160cb01bdaac98af65b Mon Sep 17 00:00:00 2001 From: Jacob Dahl Date: Tue, 17 Mar 2026 21:14:42 -0800 Subject: [PATCH] fix(crsf_rc): guard against packet_size underflow in CRSF parser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a CRSF frame arrives with packet_size < 2 (PACKET_SIZE_TYPE_SIZE), the subtraction `packet_size - PACKET_SIZE_TYPE_SIZE` underflows the uint32_t working_segment_size to 0xFFFFFFFF. The subsequent overflow check also wraps and fails to catch it. Since working_segment_size is static, the parser is permanently stalled — no further CRSF messages can be processed until reboot. Validate packet_size >= PACKET_SIZE_TYPE_SIZE early, before any subtraction, protecting both the known variable-length and unknown packet branches in a single check. Supersedes #26782 which only guarded the unknown-packet branch. --- src/drivers/rc/crsf_rc/CrsfParser.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/drivers/rc/crsf_rc/CrsfParser.cpp b/src/drivers/rc/crsf_rc/CrsfParser.cpp index bddbadfe27..5bd8eba6ce 100644 --- a/src/drivers/rc/crsf_rc/CrsfParser.cpp +++ b/src/drivers/rc/crsf_rc/CrsfParser.cpp @@ -393,6 +393,18 @@ bool CrsfParser_TryParseCrsfPacket(CrsfPacket_t *const new_packet, CrsfParserSta QueueBuffer_Peek(&rx_queue, working_index++, &packet_size); QueueBuffer_Peek(&rx_queue, working_index++, &packet_type); + // Discard packets with packet_size too small to contain type + CRC. + // Without this guard, (packet_size - PACKET_SIZE_TYPE_SIZE) underflows + // the uint32_t working_segment_size, permanently stalling the parser. + if (packet_size < PACKET_SIZE_TYPE_SIZE) { + parser_statistics->invalid_unknown_packet_sizes++; + parser_state = PARSER_STATE_HEADER; + working_segment_size = HEADER_SIZE; + working_index = 0; + buffer_count = QueueBuffer_Count(&rx_queue); + continue; + } + working_descriptor = FindCrsfDescriptor((enum CRSF_PACKET_TYPE)packet_type); // If we know what this packet is...