mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-09-02 13:13:45 +00:00
fix(esp32): stop IDF 4.4 ws-transport heap overflow crashing bridge teardown
The precompiled IDF 4.4 WebSocket transport (libtcp_transport.a) has an off-by-one in ws_connect(): when a wss:// endpoint answers the upgrade request with >=1024 bytes of HTTP response before the blank-line terminator (typical of a down broker behind a proxy serving a large error page), it writes a NUL one byte past the 1024-byte ws->buffer. Heap poisoning catches the clobbered tail canary (0xbaad5678 -> 0xbaad5600) only when the block is freed in ws_destroy() during esp_mqtt_client_destroy() - i.e. MQTTBridge::end() - so a single down broker made every deferred 'ota update' panic and reboot at teardown, before the download started. Decoded from a Heltec V3 crash backtrace on v1.16.0.11; line numbers match ESP-IDF release/v4.4 exactly. The transport code ships precompiled, so patch at link time instead: [esp32_base] wraps esp_transport_ws_init and the wrapper swaps the fresh buffer for a (WS_BUFFER_SIZE + 1)-byte allocation, making the out-of-bounds index land on owned memory. The oversized handshake then fails cleanly instead of corrupting the heap. Pass-through on IDF 5.x, where upstream already fixed it; delete with the Arduino core 3.x move. Verified: wrap resolves from ESP32WsTransportFix.cpp.o in the observer firmware.map; observer, room-server observer and plain repeater ESP32 targets build. RAK_4631_repeater failure is pre-existing (reproduced on the merge base without these changes).
This commit is contained in:
@@ -218,6 +218,12 @@ void AlertReporter::onLoop(unsigned long now_ms) {
|
||||
// already enforces this on set, but a stale prefs file or future field
|
||||
// tweak shouldn't be able to drag the floor below 1 hour and let a
|
||||
// flapping link spam the mesh.
|
||||
//
|
||||
// The rate limiter only applies between two real sends: fired_at_ms == 0
|
||||
// means "never fired since boot/config change", and treating it as a send
|
||||
// at millis()==0 would suppress every first alert until uptime reaches
|
||||
// min_interval (observed as a 30-minute alert.mqtt threshold not reporting
|
||||
// until 60 minutes after a reboot).
|
||||
uint16_t cfg_min = _obs->alert_min_interval_min;
|
||||
if (cfg_min < 60) cfg_min = 60;
|
||||
unsigned long min_interval_ms = (unsigned long)cfg_min * 60000UL;
|
||||
@@ -232,7 +238,7 @@ void AlertReporter::onLoop(unsigned long now_ms) {
|
||||
|
||||
if (_wifi.state == OK) {
|
||||
if (wifi_down && down_ms >= thresh_ms &&
|
||||
(now_ms - _wifi.fired_at_ms) >= min_interval_ms) {
|
||||
(_wifi.fired_at_ms == 0 || (now_ms - _wifi.fired_at_ms) >= min_interval_ms)) {
|
||||
char age[16];
|
||||
formatAge(down_ms, age, sizeof(age));
|
||||
uint8_t reason = MQTTBridge::getLastWifiDisconnectReason();
|
||||
@@ -282,7 +288,7 @@ void AlertReporter::onLoop(unsigned long now_ms) {
|
||||
|
||||
if (f.state == OK) {
|
||||
if (down && down_ms >= thresh_ms &&
|
||||
(now_ms - f.fired_at_ms) >= min_interval_ms) {
|
||||
(f.fired_at_ms == 0 || (now_ms - f.fired_at_ms) >= min_interval_ms)) {
|
||||
char age[16];
|
||||
formatAge(down_ms, age, sizeof(age));
|
||||
char text[100];
|
||||
|
||||
Reference in New Issue
Block a user