ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
vasprintf_stubs.cpp
Go to the documentation of this file.
1/*
2 * Linker wrap stub for vasprintf() on variants whose ROM exports a
3 * full-format vsnprintf() but no vasprintf() (ESP32-C6, newlib only).
4 *
5 * On those chips every snprintf/vsnprintf call in the image resolves to
6 * the ROM, so the newlib printf engine (_svfprintf_r, _dtoa_r and their
7 * helpers, ~20 KB) is not linked at all until something references a
8 * printf-family function the ROM lacks. esp_http_client does exactly that
9 * through vasprintf() in its header and auth helpers, so adding
10 * http_request to a build costs the whole engine on top of the HTTP and
11 * TLS code itself.
12 *
13 * This stub reimplements vasprintf() on top of the ROM vsnprintf(), which
14 * keeps the engine out of the image. It is only compiled in when codegen
15 * defines USE_ESP32_VASPRINTF_STUB, which is gated on the variant's ROM
16 * linker script and on the same newlib condition as printf_stubs.cpp.
17 */
18
20
21#if defined(USE_ESP_IDF) && defined(USE_ESP32_VASPRINTF_STUB)
22
23#include <cstdarg>
24#include <cstdio>
25#include <cstdlib>
26
27namespace esphome::esp32 {}
28
29// NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming)
30extern "C" {
31
32int __wrap_vasprintf(char **strp, const char *fmt, va_list ap) {
33 va_list ap_copy;
34 va_copy(ap_copy, ap);
35 int len = vsnprintf(nullptr, 0, fmt, ap_copy);
36 va_end(ap_copy);
37 if (len < 0) {
38 return len;
39 }
40 // vasprintf's contract is a malloc'd buffer the caller releases with free()
41 char *buf = static_cast<char *>(malloc(static_cast<size_t>(len) + 1)); // NOLINT(cppcoreguidelines-no-malloc)
42 if (buf == nullptr) {
43 return -1;
44 }
45 vsnprintf(buf, static_cast<size_t>(len) + 1, fmt, ap);
46 *strp = buf;
47 return len;
48}
49
50} // extern "C"
51// NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming)
52
53#endif // USE_ESP_IDF && USE_ESP32_VASPRINTF_STUB
va_end(args)
uint32_t len
int __wrap_vasprintf(char **strp, const char *fmt, va_list ap)