fix(rx): guard sub-minimum packSize before crcCheck (B1 OOB read)

packSize==1 давало crcCheck(1-crcBytes) → uint8 len=255 → crc8 читает dataBuffer[0..256] при массиве 38 (OOB-чтение ~217 байт). Триггер — лок преамбулы + первый байт с младшими 5 битами=1 (~1/32 ложных локов). Двойная защита: (1) ранний reject packSize 1..2 (< msg+crc) как битого; (2) конец кадра требует packSize>crcBytes, поэтому crcCheck(packSize-crcBytes) не уходит в underflow. Валидные кадры (packSize>=5) и будущие компактные (>=3) не затронуты.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-01 12:13:27 +03:00
parent fc3510c425
commit a8d32bbcef

View File

@ -862,6 +862,11 @@ void IR_DecoderRaw::writeToBuffer(bool bit, bool packTraceInvertFix)
if (i_dataBuffer == 8 * msgBytes)
{ // Ппервый байт
packSize = dataBuffer[0] & IR_MASK_MSG_INFO;
// B1: под-минимальная длина (1..2) физически не несёт CRC (min кадр = msg+crc = 3 байта) → шум/битьё.
// Без отсева packSize==1 даёт crcCheck(1-2) → len=255 → OOB-чтение dataBuffer[0..256] (массив 38).
// packSize>=3 (в т.ч. будущие компактные кадры) обрабатываются как обычно.
if (packSize != 0 && packSize < msgBytes + crcBytes)
isWrongPack = true;
}
// Тип приёма (для isReceive): выставляем сразу после первого байта, ДО проверки «Конец».
@ -872,8 +877,8 @@ void IR_DecoderRaw::writeToBuffer(bool bit, bool packTraceInvertFix)
msgTypeReceive = (dataBuffer[0] >> 5) | 0b11111000;
}
if (packSize && (i_dataBuffer == packSize * bitPerByte))
{ // Конец
if (packSize > crcBytes && (i_dataBuffer == packSize * bitPerByte))
{ // Конец (B1: packSize>crcBytes → crcCheck(packSize-crcBytes) не уходит в underflow/OOB)
packInfo.buffer = dataBuffer;
packInfo.crc = crcValue;
packInfo.err = errors;