From ddea61a4ed106397b87c6f3ed81b53c66322c44b Mon Sep 17 00:00:00 2001 From: pablo-mano Date: Tue, 19 May 2026 19:49:28 +0200 Subject: [PATCH] Fix stack smashing reboot loop caused by buffer overflow in renderContactList MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The device crashed on every boot with "Stack smashing protect failure!" whenever more than 64 contacts were stored from a previous firmware. Root cause: `filtered_indices[64]` in `renderContactList()` was written with up to MAX_CONTACTS (200) entries — a 136-element overflow that corrupted the stack canary and triggered a reboot loop. Fixes: - Grow `filtered_indices` to `MAX_CONTACTS` and add bounds guards in both the filtered and unfiltered code paths - Raise Arduino loop task stack from 8 KB to 16 KB via `CONFIG_ARDUINO_LOOP_STACK_SIZE=16384` (headroom for BLE + NVS depth) - Remove stale inline `NodePrefs` redefinition in `target.cpp` (had wrong types: `uint8_t airtime_factor` / `uint8_t rx_delay_base` instead of `float`); use the canonical `NodePrefs.h` instead Co-Authored-By: Claude Sonnet 4.6 --- .../companion_radio/ui-keyboard/UITask.cpp | 10 +++++----- variants/m5stack_cardputer/platformio.ini | 1 + variants/m5stack_cardputer/target.cpp | 20 +++---------------- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/examples/companion_radio/ui-keyboard/UITask.cpp b/examples/companion_radio/ui-keyboard/UITask.cpp index b3f047a..bba523b 100644 --- a/examples/companion_radio/ui-keyboard/UITask.cpp +++ b/examples/companion_radio/ui-keyboard/UITask.cpp @@ -333,9 +333,9 @@ void UITask::renderContactList() { int num_contacts = the_mesh.getNumContacts(); // Filter contacts by search term - int filtered_indices[64]; + int filtered_indices[MAX_CONTACTS]; int filtered_count = 0; - + if (_search_filter_length > 0) { for (int i = 0; i < num_contacts; i++) { ContactInfo contact; @@ -351,7 +351,7 @@ void UITask::renderContactList() { lower_filter[j] = tolower(_search_filter[j]); lower_filter[j+1] = '\0'; } - if (strstr(lower_name, lower_filter) != nullptr) { + if (strstr(lower_name, lower_filter) != nullptr && filtered_count < MAX_CONTACTS) { filtered_indices[filtered_count++] = i; } } @@ -359,10 +359,10 @@ void UITask::renderContactList() { num_contacts = filtered_count; } else { // No filter - show all - for (int i = 0; i < num_contacts; i++) { + for (int i = 0; i < num_contacts && i < MAX_CONTACTS; i++) { filtered_indices[i] = i; } - filtered_count = num_contacts; + filtered_count = num_contacts < MAX_CONTACTS ? num_contacts : MAX_CONTACTS; } if (num_contacts == 0) { diff --git a/variants/m5stack_cardputer/platformio.ini b/variants/m5stack_cardputer/platformio.ini index 1be4a8b..e638e6f 100644 --- a/variants/m5stack_cardputer/platformio.ini +++ b/variants/m5stack_cardputer/platformio.ini @@ -36,6 +36,7 @@ build_flags = -D PIN_BOARD_SDA=2 -D PIN_BOARD_SCL=1 -D PIN_VBAT_READ=10 ; Battery voltage ADC + -D CONFIG_ARDUINO_LOOP_STACK_SIZE=16384 build_src_filter = ${esp32_base.build_src_filter} +<../variants/m5stack_cardputer> -<../variants/m5stack_cardputer/test_main.cpp> diff --git a/variants/m5stack_cardputer/target.cpp b/variants/m5stack_cardputer/target.cpp index 86ec54a..3bc8a85 100644 --- a/variants/m5stack_cardputer/target.cpp +++ b/variants/m5stack_cardputer/target.cpp @@ -1,5 +1,8 @@ #include #include "target.h" +#ifdef HAS_GPS +#include "../../examples/companion_radio/NodePrefs.h" +#endif M5CardputerBoard board; @@ -147,23 +150,6 @@ bool CardputerSensorManager::setSettingValue(const char* name, const char* value // Sync with NodePrefs if (_node_prefs) { - struct NodePrefs { - uint8_t airtime_factor; - char node_name[32]; - float freq; uint8_t sf; uint8_t cr; - uint8_t multi_acks; - uint8_t manual_add_contacts; - float bw; - uint8_t tx_power_dbm; - uint8_t telemetry_mode_base; - uint8_t telemetry_mode_loc; - uint8_t telemetry_mode_env; - uint8_t rx_delay_base; - uint32_t ble_pin; - uint8_t advert_loc_policy; - uint8_t buzzer_quiet; - uint8_t gps_enabled; - }; NodePrefs* prefs = (NodePrefs*)_node_prefs; prefs->gps_enabled = should_enable ? 1 : 0; Serial.printf("[GPS] Updated NodePrefs: gps_enabled=%d\n", prefs->gps_enabled);