Limit http connections and add free heap check before allocating for SSL (#9693)

* Reduce maximum concurrent HTTPS connections to save memory

* Add heap check and limit connections to prevent HTTPS connection related crashes

* Use Throttle::isWithinTimespanMs for overflow-safe heap warning throttle

* Update src/mesh/http/WebServer.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix double-free heap corruption and parser leak in web server handlers

- Remove double-free in handleFsBrowseStatic, handleNodes, handleScanNetworks:
  JSONValue(const JSONArray&) shallow-copies pointers, so delete value already
  recursively frees all elements. The explicit cleanup loops were deleting the
  same pointers a second time, corrupting the ESP32 heap allocator metadata.
  This is the likely root cause of #8827 (SSL setup failures after uptime).
- Fix memory leak in handleFormUpload: two early-return paths were missing
  delete parser.
- Remove unused global HTTPClient httpClient and its includes.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Ben Meadors
2026-02-21 09:06:17 -06:00
committed by GitHub
co-authored by Copilot
parent 8f81b194d3
commit f615990c00
2 changed files with 24 additions and 22 deletions
+2 -19
View File
@@ -46,10 +46,6 @@ using namespace httpsserver;
#include "mesh/http/ContentHandler.h"
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
HTTPClient httpClient;
#define DEST_FS_USES_LITTLEFS
// We need to specify some content-type mapping, so the resources get delivered with the
@@ -344,11 +340,6 @@ void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res)
res->print(jsonString.c_str());
delete value;
// Clean up the fileList to prevent memory leak
for (auto *val : fileList) {
delete val;
}
}
void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res)
@@ -543,6 +534,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
if (name != "file") {
LOG_DEBUG("Skip unexpected field");
res->println("<p>No file found.</p>");
delete parser;
return;
}
@@ -550,6 +542,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
if (filename == "") {
LOG_DEBUG("Skip unexpected field");
res->println("<p>No file found.</p>");
delete parser;
return;
}
@@ -783,11 +776,6 @@ void handleNodes(HTTPRequest *req, HTTPResponse *res)
std::string jsonString = value->Stringify();
res->print(jsonString.c_str());
delete value;
// Clean up the nodesArray to prevent memory leak
for (auto *val : nodesArray) {
delete val;
}
}
/*
@@ -941,10 +929,5 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
std::string jsonString = value->Stringify();
res->print(jsonString.c_str());
delete value;
// Clean up the networkObjs to prevent memory leak
for (auto *val : networkObjs) {
delete val;
}
}
#endif