[web_server_idf] Reduce heap allocations by using stack buffers (#13549)

This commit is contained in:
J. Nick Koston
2026-02-10 13:56:12 -06:00
committed by GitHub
parent c65d3a0072
commit 868a2151e3
@@ -344,14 +344,15 @@ bool AsyncWebServerRequest::authenticate(const char *username, const char *passw
memcpy(user_info + user_len + 1, password, pass_len); memcpy(user_info + user_len + 1, password, pass_len);
user_info[user_info_len] = '\0'; user_info[user_info_len] = '\0';
size_t n = 0, out; // Base64 output size is ceil(input_len * 4/3) + 1, with input bounded to 256 bytes
esp_crypto_base64_encode(nullptr, 0, &n, reinterpret_cast<const uint8_t *>(user_info), user_info_len); // max output is ceil(256 * 4/3) + 1 = 343 bytes, use 350 for safety
constexpr size_t max_digest_len = 350;
auto digest = std::unique_ptr<char[]>(new char[n + 1]); char digest[max_digest_len];
esp_crypto_base64_encode(reinterpret_cast<uint8_t *>(digest.get()), n, &out, size_t out;
esp_crypto_base64_encode(reinterpret_cast<uint8_t *>(digest), max_digest_len, &out,
reinterpret_cast<const uint8_t *>(user_info), user_info_len); reinterpret_cast<const uint8_t *>(user_info), user_info_len);
return strcmp(digest.get(), auth_str + auth_prefix_len) == 0; return strcmp(digest, auth_str + auth_prefix_len) == 0;
} }
void AsyncWebServerRequest::requestAuthentication(const char *realm) const { void AsyncWebServerRequest::requestAuthentication(const char *realm) const {
@@ -861,12 +862,12 @@ esp_err_t AsyncWebServer::handle_multipart_upload_(httpd_req_t *r, const char *c
} }
}); });
// Process data // Process data - use stack buffer to avoid heap allocation
std::unique_ptr<char[]> buffer(new char[MULTIPART_CHUNK_SIZE]); char buffer[MULTIPART_CHUNK_SIZE];
size_t bytes_since_yield = 0; size_t bytes_since_yield = 0;
for (size_t remaining = r->content_len; remaining > 0;) { for (size_t remaining = r->content_len; remaining > 0;) {
int recv_len = httpd_req_recv(r, buffer.get(), std::min(remaining, MULTIPART_CHUNK_SIZE)); int recv_len = httpd_req_recv(r, buffer, std::min(remaining, MULTIPART_CHUNK_SIZE));
if (recv_len <= 0) { if (recv_len <= 0) {
httpd_resp_send_err(r, recv_len == HTTPD_SOCK_ERR_TIMEOUT ? HTTPD_408_REQ_TIMEOUT : HTTPD_400_BAD_REQUEST, httpd_resp_send_err(r, recv_len == HTTPD_SOCK_ERR_TIMEOUT ? HTTPD_408_REQ_TIMEOUT : HTTPD_400_BAD_REQUEST,
@@ -874,7 +875,7 @@ esp_err_t AsyncWebServer::handle_multipart_upload_(httpd_req_t *r, const char *c
return recv_len == HTTPD_SOCK_ERR_TIMEOUT ? ESP_ERR_TIMEOUT : ESP_FAIL; return recv_len == HTTPD_SOCK_ERR_TIMEOUT ? ESP_ERR_TIMEOUT : ESP_FAIL;
} }
if (reader->parse(buffer.get(), recv_len) != static_cast<size_t>(recv_len)) { if (reader->parse(buffer, recv_len) != static_cast<size_t>(recv_len)) {
ESP_LOGW(TAG, "Multipart parser error"); ESP_LOGW(TAG, "Multipart parser error");
httpd_resp_send_err(r, HTTPD_400_BAD_REQUEST, nullptr); httpd_resp_send_err(r, HTTPD_400_BAD_REQUEST, nullptr);
return ESP_FAIL; return ESP_FAIL;