From 3b21bc80d6b24cec86c63c9e9aa2c99c9ba9776c Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 2 Feb 2025 23:28:51 +0100 Subject: [PATCH] fix(mem): Log an error when a memory allocation fails --- src/AsyncEventSource.cpp | 7 +++- src/AsyncJson.cpp | 6 +++ src/AsyncMessagePack.cpp | 6 +++ src/AsyncWebHeader.cpp | 17 ++++++--- src/AsyncWebSocket.cpp | 17 +++++++-- src/Middleware.cpp | 16 ++++++-- src/WebAuthentication.cpp | 27 +++++++++++++- src/WebHandlers.cpp | 7 ++++ src/WebRequest.cpp | 78 ++++++++++++++++++++++++++++----------- src/WebResponses.cpp | 10 ++++- src/WebServer.cpp | 15 ++------ 11 files changed, 156 insertions(+), 50 deletions(-) diff --git a/src/AsyncEventSource.cpp b/src/AsyncEventSource.cpp index f44422db..df61714d 100644 --- a/src/AsyncEventSource.cpp +++ b/src/AsyncEventSource.cpp @@ -24,7 +24,12 @@ static String generateEventMessage(const char *message, const char *event, uint3 len += 42; // give it some overhead - str.reserve(len); + if (!str.reserve(len)) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif + return emptyString; + } if (reconnect) { str += T_retry_; diff --git a/src/AsyncJson.cpp b/src/AsyncJson.cpp index 44d515d6..ce12a694 100644 --- a/src/AsyncJson.cpp +++ b/src/AsyncJson.cpp @@ -150,6 +150,12 @@ void AsyncCallbackJsonWebHandler::handleBody(AsyncWebServerRequest *request, uin _contentLength = total; if (total > 0 && request->_tempObject == NULL && total < _maxContentLength) { request->_tempObject = malloc(total); + if (request->_tempObject == NULL) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif + return; + } } if (request->_tempObject != NULL) { memcpy((uint8_t *)(request->_tempObject) + index, data, len); diff --git a/src/AsyncMessagePack.cpp b/src/AsyncMessagePack.cpp index dd75703a..f8cb0387 100644 --- a/src/AsyncMessagePack.cpp +++ b/src/AsyncMessagePack.cpp @@ -102,6 +102,12 @@ void AsyncCallbackMessagePackWebHandler::handleBody(AsyncWebServerRequest *reque _contentLength = total; if (total > 0 && request->_tempObject == NULL && total < _maxContentLength) { request->_tempObject = malloc(total); + if (request->_tempObject == NULL) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif + return; + } } if (request->_tempObject != NULL) { memcpy((uint8_t *)(request->_tempObject) + index, data, len); diff --git a/src/AsyncWebHeader.cpp b/src/AsyncWebHeader.cpp index a12b939b..50747b84 100644 --- a/src/AsyncWebHeader.cpp +++ b/src/AsyncWebHeader.cpp @@ -17,11 +17,16 @@ AsyncWebHeader::AsyncWebHeader(const String &data) { String AsyncWebHeader::toString() const { String str; - str.reserve(_name.length() + _value.length() + 2); - str.concat(_name); - str.concat((char)0x3a); - str.concat((char)0x20); - str.concat(_value); - str.concat(asyncsrv::T_rn); + if (str.reserve(_name.length() + _value.length() + 2)) { + str.concat(_name); + str.concat((char)0x3a); + str.concat((char)0x20); + str.concat(_value); + str.concat(asyncsrv::T_rn); + } else { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif + } return str; } diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp index ea6f46db..64149c98 100644 --- a/src/AsyncWebSocket.cpp +++ b/src/AsyncWebSocket.cpp @@ -66,8 +66,9 @@ size_t webSocketSendFrame(AsyncClient *client, bool final, uint8_t opcode, bool uint8_t *buf = (uint8_t *)malloc(headLen); if (buf == NULL) { - // os_printf("could not malloc %u bytes for frame header\n", headLen); - // Serial.println("SF 3"); +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif return 0; } @@ -168,6 +169,9 @@ class AsyncWebSocketControl { _data = (uint8_t *)malloc(_len); if (_data == NULL) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif _len = 0; } else { memcpy(_data, data, len); @@ -516,6 +520,10 @@ void AsyncWebSocketClient::close(uint16_t code, const char *message) { _queueControl(WS_DISCONNECT, (uint8_t *)buf, packetLen); free(buf); return; + } else { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif } } _queueControl(WS_DISCONNECT); @@ -1289,7 +1297,10 @@ AsyncWebSocketResponse::AsyncWebSocketResponse(const String &key, AsyncWebSocket sha1(key + WS_STR_UUID, hash); #else String k; - k.reserve(key.length() + WS_STR_UUID_LEN); + if (!k.reserve(key.length() + WS_STR_UUID_LEN)) { + log_e("Failed to allocate buffer"); + return; + } k.concat(key); k.concat(WS_STR_UUID); SHA1Builder sha1; diff --git a/src/Middleware.cpp b/src/Middleware.cpp index 805eaef1..77e94c4a 100644 --- a/src/Middleware.cpp +++ b/src/Middleware.cpp @@ -99,13 +99,21 @@ bool AsyncAuthenticationMiddleware::generateHash() { switch (_authMethod) { case AsyncAuthType::AUTH_DIGEST: _credentials = generateDigestHash(_username.c_str(), _credentials.c_str(), _realm.c_str()); - _hash = true; - return true; + if (_credentials.length()) { + _hash = true; + return true; + } else { + return false; + } case AsyncAuthType::AUTH_BASIC: _credentials = generateBasicHash(_username.c_str(), _credentials.c_str()); - _hash = true; - return true; + if (_credentials.length()) { + _hash = true; + return true; + } else { + return false; + } default: return false; } diff --git a/src/WebAuthentication.cpp b/src/WebAuthentication.cpp index 3669c1a4..c80f24ba 100644 --- a/src/WebAuthentication.cpp +++ b/src/WebAuthentication.cpp @@ -86,6 +86,9 @@ String genRandomMD5() { #endif char *out = (char *)malloc(33); if (out == NULL || !getMD5((uint8_t *)(&r), 4, out)) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif return emptyString; } String res = String(out); @@ -96,6 +99,9 @@ String genRandomMD5() { static String stringMD5(const String &in) { char *out = (char *)malloc(33); if (out == NULL || !getMD5((uint8_t *)(in.c_str()), in.length(), out)) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif return emptyString; } String res = String(out); @@ -108,16 +114,33 @@ String generateDigestHash(const char *username, const char *password, const char return emptyString; } char *out = (char *)malloc(33); + if (out == NULL) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif + return emptyString; + } String in; - in.reserve(strlen(username) + strlen(realm) + strlen(password) + 2); + if (!in.reserve(strlen(username) + strlen(realm) + strlen(password) + 2)) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif + free(out); + return emptyString; + } + in.concat(username); in.concat(':'); in.concat(realm); in.concat(':'); in.concat(password); - if (out == NULL || !getMD5((uint8_t *)(in.c_str()), in.length(), out)) { + if (!getMD5((uint8_t *)(in.c_str()), in.length(), out)) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif + free(out); return emptyString; } diff --git a/src/WebHandlers.cpp b/src/WebHandlers.cpp index 575136e9..856ca85d 100644 --- a/src/WebHandlers.cpp +++ b/src/WebHandlers.cpp @@ -172,6 +172,13 @@ bool AsyncStaticWebHandler::_searchFile(AsyncWebServerRequest *request, const St // Extract the file name from the path and keep it in _tempObject size_t pathLen = path.length(); char *_tempPath = (char *)malloc(pathLen + 1); + if (_tempPath == NULL) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif + request->_tempFile.close(); + return false; + } snprintf_P(_tempPath, pathLen + 1, PSTR("%s"), path.c_str()); request->_tempObject = (void *)_tempPath; } diff --git a/src/WebRequest.cpp b/src/WebRequest.cpp index b8ada4cf..4042394f 100644 --- a/src/WebRequest.cpp +++ b/src/WebRequest.cpp @@ -129,7 +129,14 @@ void AsyncWebServerRequest::_onData(void *buf, size_t len) { if (i == len) { // No new line, just add the buffer in _temp char ch = str[len - 1]; str[len - 1] = 0; - _temp.reserve(_temp.length() + len); + if (!_temp.reserve(_temp.length() + len)) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif + _parseState = PARSE_REQ_FAIL; + _client->abort(); + return; + } _temp.concat(str); _temp.concat(ch); } else { // Found new line - extract it and parse @@ -280,9 +287,11 @@ void AsyncWebServerRequest::_addGetParams(const String ¶ms) { if (equal < 0 || equal > end) { equal = end; } - String name(params.substring(start, equal)); - String value(equal + 1 < end ? params.substring(equal + 1, end) : String()); - _params.emplace_back(urlDecode(name), urlDecode(value)); + String name = urlDecode(params.substring(start, equal)); + String value = urlDecode(equal + 1 < end ? params.substring(equal + 1, end) : emptyString); + if (name.length()) { + _params.emplace_back(name, value); + } start = end + 1; } } @@ -408,7 +417,10 @@ void AsyncWebServerRequest::_parsePlainPostChar(uint8_t data) { name = _temp.substring(0, _temp.indexOf('=')); value = _temp.substring(_temp.indexOf('=') + 1); } - _params.emplace_back(urlDecode(name), urlDecode(value), true); + name = urlDecode(name); + if (name.length()) { + _params.emplace_back(name, urlDecode(value), true); + } #ifndef TARGET_RP2040 _temp.clear(); @@ -531,6 +543,9 @@ void AsyncWebServerRequest::_parseMultipartPostByte(uint8_t data, bool last) { } _itemBuffer = (uint8_t *)malloc(RESPONSE_STREAM_BUFFER_SIZE); if (_itemBuffer == NULL) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif _multiParseState = PARSE_ERROR; return; } @@ -934,27 +949,42 @@ void AsyncWebServerRequest::requestAuthentication(AsyncAuthType method, const ch case AsyncAuthType::AUTH_BASIC: { String header; - header.reserve(strlen(T_BASIC_REALM) + strlen(realm) + 1); - header.concat(T_BASIC_REALM); - header.concat(realm); - header.concat('"'); - r->addHeader(T_WWW_AUTH, header.c_str()); + if (header.reserve(strlen(T_BASIC_REALM) + strlen(realm) + 1)) { + header.concat(T_BASIC_REALM); + header.concat(realm); + header.concat('"'); + r->addHeader(T_WWW_AUTH, header.c_str()); + } else { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif + } + break; } case AsyncAuthType::AUTH_DIGEST: { size_t len = strlen(T_DIGEST_) + strlen(T_realm__) + strlen(T_auth_nonce) + 32 + strlen(T__opaque) + 32 + 1; String header; - header.reserve(len + strlen(realm)); - header.concat(T_DIGEST_); - header.concat(T_realm__); - header.concat(realm); - header.concat(T_auth_nonce); - header.concat(genRandomMD5()); - header.concat(T__opaque); - header.concat(genRandomMD5()); - header.concat((char)0x22); // '"' - r->addHeader(T_WWW_AUTH, header.c_str()); + if (header.reserve(len + strlen(realm))) { + const String nonce = genRandomMD5(); + const String opaque = genRandomMD5(); + if (nonce.length() && opaque.length()) { + header.concat(T_DIGEST_); + header.concat(T_realm__); + header.concat(realm); + header.concat(T_auth_nonce); + header.concat(nonce); + header.concat(T__opaque); + header.concat(opaque); + header.concat((char)0x22); // '"' + r->addHeader(T_WWW_AUTH, header.c_str()); + } else { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif + } + } break; } default: break; @@ -1031,7 +1061,13 @@ String AsyncWebServerRequest::urlDecode(const String &text) const { unsigned int len = text.length(); unsigned int i = 0; String decoded; - decoded.reserve(len); // Allocate the string internal buffer - never longer from source text + // Allocate the string internal buffer - never longer from source text + if (!decoded.reserve(len)) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif + return emptyString; + } while (i < len) { char decodedChar; char encodedChar = text.charAt(i++); diff --git a/src/WebResponses.cpp b/src/WebResponses.cpp index dbcfc31a..1d1f8158 100644 --- a/src/WebResponses.cpp +++ b/src/WebResponses.cpp @@ -408,7 +408,9 @@ size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest *request, size_t len, u uint8_t *buf = (uint8_t *)malloc(outLen + headLen); if (!buf) { - // os_printf("_ack malloc %d failed\n", outLen+headLen); +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif return 0; } @@ -817,7 +819,11 @@ AsyncResponseStream::AsyncResponseStream(const char *contentType, size_t bufferS _code = 200; _contentLength = 0; _contentType = contentType; - _content.reserve(bufferSize); + if (!_content.reserve(bufferSize)) { +#ifdef ESP32 + log_e("Failed to allocate buffer"); +#endif + } } size_t AsyncResponseStream::_fillBuffer(uint8_t *buf, size_t maxLen) { diff --git a/src/WebServer.cpp b/src/WebServer.cpp index 062e9643..01dac4f3 100644 --- a/src/WebServer.cpp +++ b/src/WebServer.cpp @@ -30,9 +30,6 @@ const char *fs::FileOpenMode::append = "a"; AsyncWebServer::AsyncWebServer(uint16_t port) : _server(port) { _catchAllHandler = new AsyncCallbackWebHandler(); - if (_catchAllHandler == NULL) { - return; - } _server.onClient( [](void *s, AsyncClient *c) { if (c == NULL) { @@ -52,9 +49,7 @@ AsyncWebServer::AsyncWebServer(uint16_t port) : _server(port) { AsyncWebServer::~AsyncWebServer() { reset(); end(); - if (_catchAllHandler) { - delete _catchAllHandler; - } + delete _catchAllHandler; } AsyncWebRewrite &AsyncWebServer::addRewrite(std::shared_ptr rewrite) { @@ -179,9 +174,7 @@ void AsyncWebServer::reset() { _rewrites.clear(); _handlers.clear(); - if (_catchAllHandler != NULL) { - _catchAllHandler->onRequest(NULL); - _catchAllHandler->onUpload(NULL); - _catchAllHandler->onBody(NULL); - } + _catchAllHandler->onRequest(NULL); + _catchAllHandler->onUpload(NULL); + _catchAllHandler->onBody(NULL); }