fix: ensure icon empty string is PROGMEM, skip lookup when disabled

- When USE_ENTITY_ICON is disabled, return "" directly without
  calling through the lookup table
- When enabled, ensure the empty-string fallback (index 0 / out of
  range) is a PROGMEM char array so strncpy_P on ESP8266 is safe
This commit is contained in:
J. Nick Koston
2026-03-03 08:15:56 -10:00
parent 1108511c63
commit 4a22afb79d
2 changed files with 13 additions and 7 deletions
+9 -6
View File
@@ -49,7 +49,9 @@ void EntityBase::set_name(const char *name, uint32_t object_id_hash) {
// Weak default lookup functions — overridden by generated code in main.cpp
__attribute__((weak)) const char *entity_device_class_lookup(uint8_t) { return ""; }
__attribute__((weak)) const char *entity_uom_lookup(uint8_t) { return ""; }
__attribute__((weak)) const char *entity_icon_lookup(uint8_t) { return ""; }
// Icon empty string must be PROGMEM — on ESP8266 callers use strncpy_P to read it
static const char ENTITY_ICON_EMPTY[] PROGMEM = "";
__attribute__((weak)) const char *entity_icon_lookup(uint8_t) { return ENTITY_ICON_EMPTY; }
// Entity device class (from index)
StringRef EntityBase::get_device_class_ref() const {
@@ -74,12 +76,12 @@ std::string EntityBase::get_unit_of_measurement() const {
}
// Entity icon — buffer-based API for PROGMEM safety on ESP8266
const char *EntityBase::get_icon_to(std::span<char, MAX_ICON_LENGTH> buffer) const {
#ifdef USE_ENTITY_ICON
const char *icon = entity_icon_lookup(this->icon_idx_);
const char *EntityBase::get_icon_to([[maybe_unused]] std::span<char, MAX_ICON_LENGTH> buffer) const {
#ifndef USE_ENTITY_ICON
// No icons configured — skip lookup entirely
return "";
#else
const char *icon = entity_icon_lookup(0);
#endif
const char *icon = entity_icon_lookup(this->icon_idx_);
#ifdef USE_ESP8266
ESPHOME_strncpy_P(buffer.data(), icon, buffer.size() - 1);
buffer[buffer.size() - 1] = '\0';
@@ -87,6 +89,7 @@ const char *EntityBase::get_icon_to(std::span<char, MAX_ICON_LENGTH> buffer) con
#else
return icon;
#endif
#endif // USE_ENTITY_ICON
}
#ifndef USE_ESP8266
+4 -1
View File
@@ -109,9 +109,12 @@ def _generate_category_code(
f"static const char {var_name}[] PROGMEM = {cpp_string_escape(s)};"
)
entries = ", ".join(var_names)
# Empty string must also be PROGMEM — on ESP8266, callers use strncpy_P
empty_var = f"{table_var}_EMPTY"
lines.append(f'static const char {empty_var}[] PROGMEM = "";')
lines.append(f"static const char *const {table_var}[] PROGMEM = {{{entries}}};")
lines.append(f"const char *{lookup_fn}(uint8_t index) {{")
lines.append(f' if (index == 0 || index > {count}) return "";')
lines.append(f" if (index == 0 || index > {count}) return {empty_var};")
lines.append(f" return progmem_read_ptr(&{table_var}[index - 1]);")
lines.append("}")
return "\n".join(lines) + "\n"