diff --git a/firmware/esp32-csi-node/test/Makefile b/firmware/esp32-csi-node/test/Makefile index c794edd9..28ef8da9 100644 --- a/firmware/esp32-csi-node/test/Makefile +++ b/firmware/esp32-csi-node/test/Makefile @@ -20,6 +20,11 @@ # FUZZ_JOBS=4 # Parallel fuzzing jobs CC = clang +# ADR-110: -DCONFIG_CSI_FRAME_HE_TAGGING=1 enables the byte-18/19 HE path +# in csi_collector.c so the fuzzer exercises that code as well as the +# legacy zero-fill path. CONFIG_SOC_WIFI_HE_SUPPORT is left UNSET to +# exercise the legacy S3 branch (sig_mode/cwb/stbc). Add it to CFLAGS for +# a parallel HE-stub build if you want fuzz coverage of the C6 branch. CFLAGS = -fsanitize=fuzzer,address,undefined -g -O1 \ -Istubs -I../main \ -DCONFIG_CSI_NODE_ID=1 \ @@ -28,6 +33,7 @@ CFLAGS = -fsanitize=fuzzer,address,undefined -g -O1 \ -DCONFIG_CSI_TARGET_IP=\"192.168.1.1\" \ -DCONFIG_CSI_TARGET_PORT=5500 \ -DCONFIG_ESP_WIFI_CSI_ENABLED=1 \ + -DCONFIG_CSI_FRAME_HE_TAGGING=1 \ -Wno-unused-function STUBS_SRC = stubs/esp_stubs.c diff --git a/firmware/esp32-csi-node/test/fuzz_csi_serialize.c b/firmware/esp32-csi-node/test/fuzz_csi_serialize.c index 67cf4523..1eb3af85 100644 --- a/firmware/esp32-csi-node/test/fuzz_csi_serialize.c +++ b/firmware/esp32-csi-node/test/fuzz_csi_serialize.c @@ -60,6 +60,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) uint8_t channel; int8_t noise_floor; uint8_t out_buf_scale; /* Controls output buffer size: 0-255. */ + /* ADR-110: fuzz the new HE-branch + legacy-branch input fields too so + * the byte 18/19 encoding code path is exercised. */ + uint8_t he_inputs[2] = {0}; /* cur_bb_format (4 bits) + second (4 bits) packed */ + uint8_t legacy_inputs = 0; /* sig_mode (2) + cwb (1) + stbc (1) packed */ fuzz_read(&cursor, &remaining, &test_case, 1); fuzz_read(&cursor, &remaining, &iq_len_raw, 2); @@ -67,6 +71,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) fuzz_read(&cursor, &remaining, &channel, 1); fuzz_read(&cursor, &remaining, &noise_floor, 1); fuzz_read(&cursor, &remaining, &out_buf_scale, 1); + fuzz_read(&cursor, &remaining, he_inputs, 2); + fuzz_read(&cursor, &remaining, &legacy_inputs, 1); /* --- Test case 0: Normal operation with fuzz-controlled values --- */ @@ -75,6 +81,15 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) info.rx_ctrl.rssi = rssi; info.rx_ctrl.channel = channel & 0x0F; /* 4-bit field */ info.rx_ctrl.noise_floor = noise_floor; + /* ADR-110: feed both branch families. Only the active branch (chosen + * at compile time by CONFIG_SOC_WIFI_HE_SUPPORT) will read its fields; + * the other set is set-but-not-read. Both must be assignable without + * triggering UBSAN bitfield-overflow. */ + info.rx_ctrl.cur_bb_format = he_inputs[0] & 0x0F; /* 0..15 valid input space */ + info.rx_ctrl.second = he_inputs[1] & 0x0F; + info.rx_ctrl.sig_mode = legacy_inputs & 0x03; + info.rx_ctrl.cwb = (legacy_inputs >> 2) & 0x01; + info.rx_ctrl.stbc = (legacy_inputs >> 3) & 0x01; /* Use remaining fuzz data as I/Q buffer content. */ uint16_t iq_len; diff --git a/firmware/esp32-csi-node/test/stubs/esp_stubs.h b/firmware/esp32-csi-node/test/stubs/esp_stubs.h index be96f689..3d849a89 100644 --- a/firmware/esp32-csi-node/test/stubs/esp_stubs.h +++ b/firmware/esp32-csi-node/test/stubs/esp_stubs.h @@ -62,14 +62,28 @@ static inline esp_err_t esp_timer_delete(esp_timer_handle_t h) { (void)h; return /* ---- esp_wifi_types.h ---- */ -/** Minimal rx_ctrl fields needed by csi_serialize_frame. */ +/** Minimal rx_ctrl fields needed by csi_serialize_frame. + * + * ADR-110: the HE-tagging path in csi_collector.c references either + * (CONFIG_SOC_WIFI_HE_SUPPORT branch) cur_bb_format, second + * (legacy / S3 branch) sig_mode, cwb, stbc + * + * Both sets are unconditionally declared here so a single stub builds + * for either branch — the Makefile picks which side via -D flags. */ typedef struct { - signed rssi : 8; - unsigned channel : 4; - unsigned noise_floor : 8; - unsigned rx_ant : 2; - /* Padding to fill out the struct so it compiles. */ - unsigned _pad : 10; + signed rssi : 8; + unsigned channel : 4; + unsigned noise_floor : 8; + unsigned rx_ant : 2; + /* ADR-110 HE-branch fields (CONFIG_SOC_WIFI_HE_SUPPORT path) */ + unsigned cur_bb_format : 4; /**< 0=11b 1=11g/a 2=HT 3=VHT 4=HE-SU 5=HE-MU 6=HE-ER-SU 7=HE-TB */ + unsigned second : 4; /**< secondary 40 MHz channel offset */ + /* ADR-110 legacy-branch fields (pre-HE chips) */ + unsigned sig_mode : 2; /**< 0=non-HT 1=HT 3=VHT */ + unsigned cwb : 1; /**< 0=20 MHz 1=40 MHz */ + unsigned stbc : 1; /**< STBC flag */ + /* Padding to keep alignment predictable. */ + unsigned _pad : 18; } wifi_pkt_rx_ctrl_t; /** Minimal wifi_csi_info_t needed by csi_serialize_frame. */