Procházet zdrojové kódy

fix(rf): guard the 0x45 decode against an invalid g_curSlot (out-of-bounds -> reset)

The F1/0x45 TLV decode in rfConnTx indexes g_in[], g_lastSeq[], steamDownMs[],
steamWasDown[], offHoldMs[], offFired[], chWant[], chCnt[] directly by
g_curSlot. g_curSlot is -1 when idle (and on rf_diag / console-driven TXs that
don't set it), so an F1 decoded with no valid slot writes g_in[-1] etc. -- an
out-of-bounds write that corrupts adjacent RAM and can HardFault, which the
watchdog turns into a device reset. Matches the "connection-starting sometimes
resets the puck" report (the connect window is when stray/edge F-replies are
most likely while slot state is in flux).

Require 0 <= g_curSlot < NSLOT before the decode touches any per-slot state.
Defensive and free when g_curSlot is already valid (the normal poll path).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Jariullah Safi před 4 měsíci
rodič
revize
e5877dbb5c
1 změnil soubory, kde provedl 5 přidání a 1 odebrání
  1. 5 1
      OpenPuck/rf_link.cpp

+ 5 - 1
OpenPuck/rf_link.cpp

@@ -379,7 +379,11 @@ uint8_t rfConnTx(uint8_t ch, uint8_t s1, const uint8_t *payload, uint8_t plen,
 				}
 			}
 			bool isF1 = (rtype == 0xF1);
-			if (isF1) {
+			// The whole 0x45 decode below indexes g_in[]/g_lastSeq[]/steamDownMs[]/offHoldMs[]/chWant[]/...
+			// by g_curSlot directly. g_curSlot is -1 when idle (and on rf_diag/console-driven TXs), so an F1
+			// decoded with no valid slot would write g_in[-1] etc. -> out-of-bounds -> memory corruption ->
+			// HardFault/reset. Require a valid slot before touching any per-slot state.
+			if (isF1 && g_curSlot >= 0 && g_curSlot < NSLOT) {
 				g_connF1++;
 				// walk ALL type6 TLVs (= HID report 0x45); taking only [0] halves the rate. idx is INT,
 				// not uint8_t: tlen 0xFE would make idx+=tlen+2 wrap mod-256 -> infinite loop -> USB hang.