Zum Inhalt

heap_trace dumps — 2026-05-04, Rev A

Two passive heap_trace windows captured from the live Rev A device (192.168.23.125, dataSource=1 / mempool+Kraken) via the /api/diag/heap_trace/{start,stop} endpoints.

Firmware HEAD: 3a3efd9 (post-format-fixup, after the cert-bundle mitigation in fe8d1d0 was already in place — so these dumps show the residual leak that PSRAM-routing only displaces, not the original internal-heap drift).

File Window Records cap Notes
window_90s.json 90 s 26 256 Initial capture, kernel of the steady-state
window_600s.json 600 s 107 256 Long capture, ~4× more records

Schema

{
  "count":    <number of leak records>,
  "capacity": <heap_trace buffer slots, currently 256>,
  "leaks": [
    {
      "sz":   <bytes>,
      "addr": "<heap address as hex string>",
      "cc":   <ccount cycle counter at alloc time>,
      "pcs":  ["<frame0>", "<frame1>", "<frame2>", "<frame3>"]
    },
  ]
}

pcs[] is CONFIG_HEAP_TRACING_STACK_DEPTH=4 deep. Symbol resolution for every distinct PC across both windows is in symbols.txt.

Cert-bundle signature (the upstream issue)

The dominant leak chain across both windows resolves to:

heap_caps_malloc_default     heap_caps.c:120
calloc                       esp_libc/src/heap.c:46
mbedtls_calloc               platform.c:50
esp_crt_copy_asn1            esp_crt_bundle.c:440  ← X.509 fragment alloc
esp_crt_copy_asn1            esp_crt_bundle.c:448  ← X.509 fragment alloc
esp_crt_ca_cb_callback       esp_crt_bundle.c:489
x509_crt_verify_chain        x509_crt.c:2578

Per-handshake fingerprint (size histogram of dominant chain in 90 s window): 2 / 3 / 12 / 16 / 24 / 32 / 45 / 81 / 168 B. Same fragments on every TLS reconnect.

Filed upstream at https://github.com/espressif/esp-idf/issues/18550.

Other PC chains visible in the dumps

The 600 s window also surfaces leaks from esp_http_client_init, esp_http_client_set_url, http_header_*, mbedtls_ssl_set_hostname, esp_transport_*, and pbuf_alloc. Those are transient allocations that heap_trace correctly snapshots as live at trace-stop time — they get freed when the corresponding HTTP/TCP session closes. They are not the cert-bundle leak. The cert-bundle leak is distinguished by the esp_crt_* frames in pcs[] and the per-handshake repetition of the same byte sizes.

Reproducing

curl -X POST http://<rev-a-ip>/api/diag/heap_trace/start
sleep 600
curl -X POST http://<rev-a-ip>/api/diag/heap_trace/stop > window_600s.json

Endpoints are guarded by #if CONFIG_HEAP_TRACING_STANDALONE, which ships in the Rev A build (see build-rev-a/sdkconfig). Resolve PCs with xtensa-esp32s3-elf-addr2line -e build-rev-a/btclock_v4.elf -f -p.