From 05575a28d5e71dd69ef3e444836c6a316df8f907 Mon Sep 17 00:00:00 2001 From: Chris Sutcliff Date: Mon, 19 Oct 2026 20:52:21 +0100 Subject: [PATCH] fix(upload): don't crash when an upload is rejected --- CHANGELOG_LATEST.md | 1 + src/ESP32React/UploadFileService.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 6d1651fb0..9a9d71384 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -34,6 +34,7 @@ This release is based on the latest Espressif/Arduino core version 3. It brings - restart from the WebUI (Restart button, firmware/settings upload) only happened while the browser tab stayed open. If the tab was closed the restart was silently dropped after 5 minutes, leaving a new firmware uninstalled. EMS-ESP now restarts on its own if the WebUI hasn't picked up the pending restart within 10 seconds - a firmware upload from a script or `curl` was accepted (`md5_ok`) but EMS-ESP didn't restart into it: the client closing the connection after the upload was treated as an aborted upload, which cancelled the pending restart +- EMS-ESP crashed and restarted when an upload was rejected, for example an empty or invalid MD5 file. The error code was kept in the request's `_tempObject`, which the web server frees as heap memory when the request ends - shunting yard show json - `system/sendmail` called from a Command or the Scheduler computed its value twice, which stripped the quotes from literal text and then failed on characters like `!`. Also shunting yard treated a `?` inside a quoted string as a ternary, so text like `"too hot?"` returned nothing - memory leak when using different timezones for ems-esp and thermostat[#3184](https://github.com/emsesp/EMS-ESP32/issues/3184) diff --git a/src/ESP32React/UploadFileService.cpp b/src/ESP32React/UploadFileService.cpp index a13a144a5..72ca26059 100644 --- a/src/ESP32React/UploadFileService.cpp +++ b/src/ESP32React/UploadFileService.cpp @@ -151,7 +151,7 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri void UploadFileService::uploadComplete(AsyncWebServerRequest * request) { if (request->_tempObject) { - const int code = static_cast(reinterpret_cast(request->_tempObject)); + const int code = *static_cast(request->_tempObject); if (!_response_sent && code >= 400) { request->send(request->beginResponse(code)); _response_sent = true; @@ -241,7 +241,12 @@ void UploadFileService::handleError(AsyncWebServerRequest * request, int code) { if (request->_tempObject) { return; } - request->_tempObject = reinterpret_cast(static_cast(code)); // stop later chunks from retrying the write + // stop later chunks from retrying the write. The request destructor frees _tempObject, so it must be heap memory + auto * error = static_cast(malloc(sizeof(int))); + if (error) { + *error = code; + } + request->_tempObject = error; emsesp::EMSESP::logger().info("Upload error: %d", code); emsesp::EMSESP::system_.uart_init(); // re-enable UART