diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index c63e55d159..85609bd31f 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -90,16 +90,14 @@ void HttpRequestUpdate::update_task(void *params) { UPDATE_RETURN; } size_t read_index = container->get_bytes_read(); + size_t content_length = container->content_length; + + container->end(); + container.reset(); // Release ownership of the container's shared_ptr bool valid = false; - { // Ensures the response string falls out of scope and deallocates before the task ends - std::string response((char *) data, read_index); - allocator.deallocate(data, container->content_length); - - container->end(); - container.reset(); // Release ownership of the container's shared_ptr - - valid = json::parse_json(response, [this_update](JsonObject root) -> bool { + { // Scope to ensure JsonDocument is destroyed before deallocating buffer + valid = json::parse_json(data, read_index, [this_update](JsonObject root) -> bool { if (!root[ESPHOME_F("name")].is() || !root[ESPHOME_F("version")].is() || !root[ESPHOME_F("builds")].is()) { ESP_LOGE(TAG, "Manifest does not contain required fields"); @@ -137,6 +135,7 @@ void HttpRequestUpdate::update_task(void *params) { return false; }); } + allocator.deallocate(data, content_length); if (!valid) { ESP_LOGE(TAG, "Failed to parse JSON from %s", this_update->source_url_.c_str()); @@ -157,17 +156,12 @@ void HttpRequestUpdate::update_task(void *params) { } } - { // Ensures the current version string falls out of scope and deallocates before the task ends - std::string current_version; #ifdef ESPHOME_PROJECT_VERSION - current_version = ESPHOME_PROJECT_VERSION; + this_update->update_info_.current_version = ESPHOME_PROJECT_VERSION; #else - current_version = ESPHOME_VERSION; + this_update->update_info_.current_version = ESPHOME_VERSION; #endif - this_update->update_info_.current_version = current_version; - } - bool trigger_update_available = false; if (this_update->update_info_.latest_version.empty() || diff --git a/esphome/components/json/json_util.cpp b/esphome/components/json/json_util.cpp index 869d29f92e..69f8bfc61a 100644 --- a/esphome/components/json/json_util.cpp +++ b/esphome/components/json/json_util.cpp @@ -25,8 +25,13 @@ std::string build_json(const json_build_t &f) { } bool parse_json(const std::string &data, const json_parse_t &f) { + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson + return parse_json(reinterpret_cast(data.c_str()), data.size(), f); +} + +bool parse_json(const uint8_t *data, size_t len, const json_parse_t &f) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - JsonDocument doc = parse_json(reinterpret_cast(data.c_str()), data.size()); + JsonDocument doc = parse_json(data, len); if (doc.overflowed() || doc.isNull()) return false; return f(doc.as()); diff --git a/esphome/components/json/json_util.h b/esphome/components/json/json_util.h index 91cc84dc14..ca074926bd 100644 --- a/esphome/components/json/json_util.h +++ b/esphome/components/json/json_util.h @@ -50,6 +50,8 @@ std::string build_json(const json_build_t &f); /// Parse a JSON string and run the provided json parse function if it's valid. bool parse_json(const std::string &data, const json_parse_t &f); +/// Parse JSON from raw bytes and run the provided json parse function if it's valid. +bool parse_json(const uint8_t *data, size_t len, const json_parse_t &f); /// Parse a JSON string and return the root JsonDocument (or an unbound object on error) JsonDocument parse_json(const uint8_t *data, size_t len);