mirror of
https://github.com/ruvnet/RuView
synced 2026-07-23 17:33:20 +00:00
fix(qemu): resolve 23 bugs from deep code review
CRITICAL: - inject_fault.py: make nvs_corrupt write actual bytes via --flash arg; heap_exhaust and corrupt_frame now pause VM with honest WARNING about GDB stub requirement for real memory writes - firmware-qemu.yml: remove github.run_id from cache key (was causing 100% cache miss rate, rebuilding QEMU every run) - mock_csi.c: change scenario_elapsed_ms() to int64_t (uint32 wrapped at ~49 days) HIGH: - qemu-mesh-test.sh: pass --results flag to validate_mesh_test.py (was passing positional arg to named-only parameter) - test/Makefile: separate corpus directories per fuzz target (corpus_serialize/, corpus_edge/, corpus_nvs/) - qemu-snapshot-test.sh: replace log truncation with tail-based extraction (truncation created sparse file while QEMU held fd) MEDIUM: - mock_csi.c: reset s_mac_filter_initialized in mock_csi_init() - mock_csi.c: fix LFSR polynomial comment (32,31,29,1 not 32,22,2,1) - sdkconfig.coverage: add FreeRTOS timer stack 4096 and WDT tuning - firmware-qemu.yml: replace continue-on-error with FUZZER_CRASH env - qemu-chaos-test.sh: rename heap_pressure to heap_exhaust for consistency - validate_qemu_output.py: fix docstring "14 checks" -> "16 checks" - generate_nvs_matrix.py: deduplicate temp file cleanup paths LOW: - mock_csi.c: remove M_PI float suffix, fix overflow burst flag - qemu-snapshot-test.sh: fix now_ms() for macOS date +%s%N - ADR-061: fix scenario 8 RSSI range to -90...-10 dBm - launch.json: remove contradictory compound debug config Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -80,7 +80,7 @@ static const char *TAG = "mock_csi";
|
||||
|
||||
/** Pi constant. */
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846f
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
/* ---- Channel sweep table ---- */
|
||||
@@ -101,7 +101,7 @@ static const uint8_t s_bad_mac[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
|
||||
/**
|
||||
* 32-bit Galois LFSR for deterministic pseudo-random noise.
|
||||
* Avoids stdlib rand() which may not be available on ESP32 bare-metal.
|
||||
* Taps: bits 32, 22, 2, 1 (maximal-length polynomial).
|
||||
* Taps: bits 32, 31, 29, 1 (Galois LFSR polynomial 0xD0000001).
|
||||
*/
|
||||
static uint32_t s_lfsr = 0xDEADBEEF;
|
||||
|
||||
@@ -110,7 +110,7 @@ static uint32_t lfsr_next(void)
|
||||
uint32_t lsb = s_lfsr & 1u;
|
||||
s_lfsr >>= 1;
|
||||
if (lsb) {
|
||||
s_lfsr ^= 0xD0000001u; /* x^32 + x^22 + x^2 + x^1 */
|
||||
s_lfsr ^= 0xD0000001u; /* x^32 + x^31 + x^29 + x^1 */
|
||||
}
|
||||
return s_lfsr;
|
||||
}
|
||||
@@ -130,6 +130,12 @@ static float lfsr_float(void)
|
||||
static mock_state_t s_state;
|
||||
static esp_timer_handle_t s_timer = NULL;
|
||||
|
||||
/** Tracks whether the MAC filter has been set up in gen_mac_filter. */
|
||||
static bool s_mac_filter_initialized = false;
|
||||
|
||||
/** Tracks whether the overflow burst has fired in gen_ring_overflow. */
|
||||
static bool s_overflow_burst_done = false;
|
||||
|
||||
/* External NVS config (for MAC filter scenario). */
|
||||
extern nvs_config_t g_nvs_config;
|
||||
|
||||
@@ -157,9 +163,9 @@ static float channel_to_lambda(uint8_t channel)
|
||||
|
||||
/* ---- Helper: elapsed ms since scenario start ---- */
|
||||
|
||||
static uint32_t scenario_elapsed_ms(void)
|
||||
static int64_t scenario_elapsed_ms(void)
|
||||
{
|
||||
uint32_t now = (uint32_t)(esp_timer_get_time() / 1000);
|
||||
int64_t now = esp_timer_get_time() / 1000;
|
||||
return now - s_state.scenario_start_ms;
|
||||
}
|
||||
|
||||
@@ -277,7 +283,7 @@ static void gen_walking(uint8_t *iq_buf, uint8_t *channel, int8_t *rssi)
|
||||
*/
|
||||
static void gen_fall(uint8_t *iq_buf, uint8_t *channel, int8_t *rssi)
|
||||
{
|
||||
uint32_t elapsed = scenario_elapsed_ms();
|
||||
int64_t elapsed = scenario_elapsed_ms();
|
||||
uint32_t duration = CONFIG_CSI_MOCK_SCENARIO_DURATION_MS;
|
||||
|
||||
/* Fall occurs at 70% of scenario duration. */
|
||||
@@ -403,7 +409,6 @@ static void gen_mac_filter(uint8_t *iq_buf, uint8_t *channel, int8_t *rssi,
|
||||
bool *skip_inject)
|
||||
{
|
||||
/* Set up the filter MAC to match s_good_mac on first frame of this scenario. */
|
||||
static bool s_mac_filter_initialized = false;
|
||||
if (!s_mac_filter_initialized) {
|
||||
memcpy(g_nvs_config.filter_mac, s_good_mac, 6);
|
||||
g_nvs_config.filter_mac_set = 1;
|
||||
@@ -439,10 +444,10 @@ static void gen_ring_overflow(uint8_t *iq_buf, uint8_t *channel, int8_t *rssi,
|
||||
*channel = 6;
|
||||
*rssi = -50;
|
||||
|
||||
/* Only burst on the first timer tick of this scenario. */
|
||||
uint32_t elapsed = scenario_elapsed_ms();
|
||||
if (elapsed < MOCK_CSI_INTERVAL_MS + 10) {
|
||||
/* Burst once on the first timer tick of this scenario. */
|
||||
if (!s_overflow_burst_done) {
|
||||
*burst_count = OVERFLOW_BURST_COUNT;
|
||||
s_overflow_burst_done = true;
|
||||
} else {
|
||||
*burst_count = 1;
|
||||
}
|
||||
@@ -454,7 +459,7 @@ static void gen_ring_overflow(uint8_t *iq_buf, uint8_t *channel, int8_t *rssi,
|
||||
*/
|
||||
static void gen_boundary_rssi(uint8_t *iq_buf, uint8_t *channel, int8_t *rssi)
|
||||
{
|
||||
uint32_t elapsed = scenario_elapsed_ms();
|
||||
int64_t elapsed = scenario_elapsed_ms();
|
||||
uint32_t duration = CONFIG_CSI_MOCK_SCENARIO_DURATION_MS;
|
||||
|
||||
/* Linear sweep: -90 to -10 dBm. */
|
||||
@@ -492,7 +497,7 @@ static void advance_scenario(void)
|
||||
}
|
||||
|
||||
s_state.scenario = s_state.all_idx;
|
||||
s_state.scenario_start_ms = (uint32_t)(esp_timer_get_time() / 1000);
|
||||
s_state.scenario_start_ms = esp_timer_get_time() / 1000;
|
||||
|
||||
/* Reset per-scenario state. */
|
||||
s_state.person_x = 1.0f;
|
||||
@@ -521,7 +526,7 @@ static void mock_timer_cb(void *arg)
|
||||
if (s_state.scenario == MOCK_SCENARIO_ALL ||
|
||||
(s_state.all_idx > 0 && s_state.all_idx < MOCK_SCENARIO_COUNT)) {
|
||||
/* We're running in sequential mode. */
|
||||
uint32_t elapsed = scenario_elapsed_ms();
|
||||
int64_t elapsed = scenario_elapsed_ms();
|
||||
if (elapsed >= CONFIG_CSI_MOCK_SCENARIO_DURATION_MS) {
|
||||
advance_scenario();
|
||||
}
|
||||
@@ -619,8 +624,10 @@ esp_err_t mock_csi_init(uint8_t scenario)
|
||||
s_state.person_speed = WALK_SPEED_MS;
|
||||
s_state.person2_x = 4.0f;
|
||||
s_state.person2_speed = WALK_SPEED_MS * 0.6f;
|
||||
s_state.scenario_start_ms = (uint32_t)(esp_timer_get_time() / 1000);
|
||||
s_state.scenario_start_ms = esp_timer_get_time() / 1000;
|
||||
s_all_done = false;
|
||||
s_mac_filter_initialized = false;
|
||||
s_overflow_burst_done = false;
|
||||
|
||||
/* Reset LFSR to deterministic seed. */
|
||||
s_lfsr = 0xDEADBEEF;
|
||||
|
||||
@@ -70,7 +70,7 @@ typedef struct {
|
||||
float person2_speed; /**< Second person movement speed. */
|
||||
uint8_t channel_idx; /**< Index into channel sweep table. */
|
||||
int8_t rssi_sweep; /**< Current RSSI for boundary sweep. */
|
||||
uint32_t scenario_start_ms; /**< Timestamp when current scenario started. */
|
||||
int64_t scenario_start_ms; /**< Timestamp when current scenario started. */
|
||||
uint8_t all_idx; /**< Current scenario index in SCENARIO_ALL mode. */
|
||||
} mock_state_t;
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ CONFIG_CSI_TARGET_IP="10.0.2.2"
|
||||
CONFIG_CSI_MOCK_SCENARIO_DURATION_MS=5000
|
||||
CONFIG_CSI_MOCK_LOG_FRAMES=y
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# FreeRTOS and watchdog: match sdkconfig.qemu for QEMU timing tolerance
|
||||
# ---------------------------------------------------------------------------
|
||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
||||
CONFIG_ESP_TASK_WDT_TIMEOUT_S=30
|
||||
CONFIG_ESP_INT_WDT_TIMEOUT_MS=800
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Logging and display
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -61,19 +61,19 @@ fuzz_nvs: fuzz_nvs_config.c $(STUBS_SRC)
|
||||
|
||||
# --- Run targets ---
|
||||
run_serialize: fuzz_serialize
|
||||
@mkdir -p corpus
|
||||
./fuzz_serialize corpus/ -max_total_time=$(FUZZ_DURATION) -max_len=2048 -jobs=$(FUZZ_JOBS)
|
||||
@mkdir -p corpus_serialize
|
||||
./fuzz_serialize corpus_serialize/ -max_total_time=$(FUZZ_DURATION) -max_len=2048 -jobs=$(FUZZ_JOBS)
|
||||
|
||||
run_edge: fuzz_edge
|
||||
@mkdir -p corpus
|
||||
./fuzz_edge corpus/ -max_total_time=$(FUZZ_DURATION) -max_len=4096 -jobs=$(FUZZ_JOBS)
|
||||
@mkdir -p corpus_edge
|
||||
./fuzz_edge corpus_edge/ -max_total_time=$(FUZZ_DURATION) -max_len=4096 -jobs=$(FUZZ_JOBS)
|
||||
|
||||
run_nvs: fuzz_nvs
|
||||
@mkdir -p corpus
|
||||
./fuzz_nvs corpus/ -max_total_time=$(FUZZ_DURATION) -max_len=256 -jobs=$(FUZZ_JOBS)
|
||||
@mkdir -p corpus_nvs
|
||||
./fuzz_nvs corpus_nvs/ -max_total_time=$(FUZZ_DURATION) -max_len=256 -jobs=$(FUZZ_JOBS)
|
||||
|
||||
run_all: run_serialize run_edge run_nvs
|
||||
|
||||
clean:
|
||||
rm -f fuzz_serialize fuzz_edge fuzz_nvs
|
||||
rm -rf corpus/
|
||||
rm -rf corpus_serialize/ corpus_edge/ corpus_nvs/
|
||||
|
||||
Reference in New Issue
Block a user