[core] Catch heap allocating helper calls with explicit template arguments (#20391)

This commit is contained in:
J. Nick Koston
2026-10-10 02:00:41 +00:00
committed by GitHub
parent 41cc96bbb8
commit 0ae24f7536
3 changed files with 33 additions and 10 deletions
+9 -9
View File
@@ -1,5 +1,6 @@
#include "debug_component.h"
#ifdef USE_ZEPHYR
#include <cinttypes>
#include <climits>
#include "esphome/core/alloc_helpers.h"
#include "esphome/core/log.h"
@@ -400,18 +401,17 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE>
#endif
}
#endif
auto uicr = [](volatile uint32_t *data, uint8_t size) {
std::string res;
// 13 words of 8 hex digits, separated by spaces
char uicr_buf[13 * 9];
auto uicr = [&uicr_buf](volatile uint32_t *data, uint8_t size) {
size_t len = 0;
for (size_t i = 0; i < size; i++) {
if (i > 0) {
res += ' ';
}
res += format_hex_pretty<uint32_t>(data[i], '\0', false);
len = buf_append_printf(uicr_buf, sizeof(uicr_buf), len, i > 0 ? " %08" PRIX32 : "%08" PRIX32, data[i]);
}
return res;
return uicr_buf;
};
ESP_LOGD(TAG, " NRFFW %s", uicr(NRF_UICR->NRFFW, 13).c_str());
ESP_LOGD(TAG, " NRFHW %s", uicr(NRF_UICR->NRFHW, 12).c_str());
ESP_LOGD(TAG, " NRFFW %s", uicr(NRF_UICR->NRFFW, 13));
ESP_LOGD(TAG, " NRFHW %s", uicr(NRF_UICR->NRFHW, 12));
#ifdef ESPHOME_LOG_HAS_VERBOSE
log_peripherals_info();
#endif
+2 -1
View File
@@ -1065,7 +1065,8 @@ HEAP_ALLOCATING_HELPERS = {
r"str_sprintf|"
r"str_snprintf|"
r"value_accuracy_to_string"
r")\s*\(" + CPP_RE_EOL,
# Explicit template arguments at any nesting depth, e.g. format_hex<std::array<uint8_t, 4>>(
r")\s*(?:<[^;{}()\n]*>\s*)?\(" + CPP_RE_EOL,
include=cpp_include,
exclude=[
# The definitions themselves
+22
View File
@@ -444,6 +444,28 @@ def test_log_tag_as_string_ignores_logging(line: str) -> None:
assert not ci_custom.lint_log_tag_as_string("test.cpp", line + "\n")
@pytest.mark.parametrize(
("content", "flagged"),
[
("auto s = format_hex_pretty(data, len);\n", True),
# Explicit template arguments must not hide the call
("auto s = format_hex_pretty<uint32_t>(v, '\\0', false);\n", True),
("auto s = format_hex<std::array<uint8_t, 4>>(arr);\n", True),
(
"auto s = format_hex<std::conditional_t<true, std::make_unsigned_t<int>, uint64_t>>(v);\n",
True,
),
("auto s = format_hex < 3;\n", False),
("format_hex_pretty_to(buf, sizeof(buf), data, len);\n", False),
],
)
def test_heap_allocating_helpers_detection(content: str, flagged: bool) -> None:
errs = ci_custom.lint_no_heap_allocating_helpers(
Path("esphome/components/x/x.cpp"), content
)
assert bool(errs) is flagged
# --- rule: every component __init__.py defines DOMAIN as its own name ---