From f8c9cf8fd98439e7f39a34f45a3d9998aa3d8d7c Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 16 Dec 2025 22:37:58 +0000 Subject: [PATCH] Use PROGMEM for version text sensor strings on ESP8266 Build version string incrementally from PROGMEM literals using ESPHOME_strncpy_P and ESPHOME_strncat_P. Write hash and build time directly into buffer without temporary variables. Calculate buffer size based on actual components needed. Add ESPHOME_strncat_P macro to progmem.h for cross-platform PROGMEM string concatenation. --- .../version/version_text_sensor.cpp | 27 +++++++++---------- esphome/core/progmem.h | 2 ++ 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/esphome/components/version/version_text_sensor.cpp b/esphome/components/version/version_text_sensor.cpp index 33ff35f0019..56df4e96bb7 100644 --- a/esphome/components/version/version_text_sensor.cpp +++ b/esphome/components/version/version_text_sensor.cpp @@ -3,6 +3,7 @@ #include "esphome/core/log.h" #include "esphome/core/version.h" #include "esphome/core/helpers.h" +#include "esphome/core/progmem.h" namespace esphome { namespace version { @@ -11,26 +12,24 @@ static const char *const TAG = "version.text_sensor"; void VersionTextSensor::setup() { static const char PREFIX[] PROGMEM = ESPHOME_VERSION " (config hash 0x"; - char version_str[128]; + static const char BUILT_STR[] PROGMEM = ", built "; + // Buffer size: PREFIX + 8 hex chars + BUILT_STR + BUILD_TIME_STR_SIZE + ")" + null + constexpr size_t BUF_SIZE = sizeof(PREFIX) + 8 + sizeof(BUILT_STR) + esphome::Application::BUILD_TIME_STR_SIZE + 2; + char version_str[BUF_SIZE]; -#ifdef USE_ESP8266 - strcpy_P(version_str, PREFIX); -#else - strcpy(version_str, PREFIX); -#endif + ESPHOME_strncpy_P(version_str, PREFIX, sizeof(version_str)); - char hash_str[9]; - snprintf(hash_str, sizeof(hash_str), "%08" PRIx32, App.get_config_hash()); - strcat(version_str, hash_str); + size_t len = strlen(version_str); + snprintf(version_str + len, sizeof(version_str) - len, "%08" PRIx32, App.get_config_hash()); if (!this->hide_timestamp_) { - strcat(version_str, ", built: "); - char build_time_str[esphome::Application::BUILD_TIME_STR_SIZE]; - App.get_build_time_string(build_time_str); - strcat(version_str, build_time_str); + size_t len = strlen(version_str); + ESPHOME_strncat_P(version_str, BUILT_STR, sizeof(version_str) - len - 1); + ESPHOME_strncat_P(version_str, ESPHOME_BUILD_TIME_STR, sizeof(version_str) - strlen(version_str) - 1); } - strcat(version_str, ")"); + strncat(version_str, ")", sizeof(version_str) - strlen(version_str) - 1); + version_str[sizeof(version_str) - 1] = '\0'; this->publish_state(version_str); } float VersionTextSensor::get_setup_priority() const { return setup_priority::DATA; } diff --git a/esphome/core/progmem.h b/esphome/core/progmem.h index f9508945e87..d1594f47e73 100644 --- a/esphome/core/progmem.h +++ b/esphome/core/progmem.h @@ -9,8 +9,10 @@ #define ESPHOME_F(string_literal) F(string_literal) #define ESPHOME_PGM_P PGM_P #define ESPHOME_strncpy_P strncpy_P +#define ESPHOME_strncat_P strncat_P #else #define ESPHOME_F(string_literal) (string_literal) #define ESPHOME_PGM_P const char * #define ESPHOME_strncpy_P strncpy +#define ESPHOME_strncat_P strncat #endif