Files
esp-idf/tools/test_apps/system/kasan_test
Meet Patel 383e9adb82 feat(kasan): add Kernel Address Sanitizer (KASAN) support for ESP-IDF
Add KASAN support for detecting heap memory safety bugs (buffer
overflows, underflows, use-after-free) at runtime using compiler
instrumentation and shadow memory. Gated behind
CONFIG_IDF_EXPERIMENTAL_FEATURES, with touch points kept to esp_system
and heap so other components stay untouched.

- Core runtime (esp_system/kasan.c, esp_kasan.h): nibble-based shadow
  memory in DRAM, poison/unpoison, per-access validation, and __asan_*
  stubs; hot-path stubs in IRAM so they stay valid with the flash cache
  off. Shadow init runs before heap bring-up.
- Heap integration (heap/heap_kasan*.c): alloc/free hooks add redzones,
  a quarantine FIFO, and shadow updates.
- Panic handling: disable checks once at the panic handler entry so
  backtrace and stack dumps can read redzones without nested reports.
- Build system: -fsanitize=kernel-address for app code, with HAL, SoC,
  esp_rom, SPI flash, esp_hw_support, bootloader_support, FreeRTOS, and
  heap internals excluded from instrumentation.
- Test app (tools/test_apps/system/kasan_test): Unity tests for
  overflow, underflow, use-after-free, and all sized __asan_* stubs,
  with halt and no-halt configurations.
- Docs: document KASAN in the heap memory debugging guide (EN and CN).
2026-06-24 11:27:00 +05:30
..

Supported Targets ESP32 ESP32-C2 ESP32-C3 ESP32-C5 ESP32-C6 ESP32-C61 ESP32-H2 ESP32-H21 ESP32-H4 ESP32-P4 ESP32-S2 ESP32-S3 ESP32-S31

KASAN Test Application

This test application validates the Kernel Address Sanitizer (KASAN) integration in ESP-IDF by deliberately triggering memory safety bugs and checking that KASAN detects and reports them before calling the panic handler.

Test Cases

Test Description Expected Outcome
overflow 1-byte write past end of 16-byte heap allocation KASAN WRITE error + panic
use_after_free Write to freed heap block KASAN WRITE error + panic
uaf_read Read from freed heap block KASAN READ error + panic
underflow Write before start of allocation (into left redzone) KASAN WRITE error + panic
large_overflow memset of 16 bytes into an 8-byte buffer KASAN WRITE error + panic
no_bug Clean alloc/use/free cycle Completes without panic
asan stubs valid access no error Direct calls to every sized __asan_load<N>_noabort and __asan_store<N>_noabort stub (N in {1, 2, 4, 8, 16, N}) on a valid buffer Completes without panic; covers all 12 stubs
asan stubs poisoned access all sizes (no_halt only) Same 12 stubs called on a freed pointer Exactly 12 KASAN errors reported

Building

cd tools/test_apps/system/kasan_test
idf.py set-target esp32c6
idf.py build

Or to select a specific test case:

idf.py -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.ci.overflow" build

Prerequisites

The following Kconfig options must be set (they are pre-configured in sdkconfig.defaults):

  • CONFIG_IDF_EXPERIMENTAL_FEATURES=y – Required to expose KASAN in menuconfig
  • CONFIG_COMPILER_KASAN=y – Enable KASAN instrumentation
  • CONFIG_ESP_TASK_WDT_EN=n – Unity menu blocks IDLE until you press Enter or select a test; required for manual idf.py monitor as well as pytest

CONFIG_COMPILER_KASAN automatically selects CONFIG_HEAP_USE_HOOKS. Redzone size (8 bytes), quarantine size (8192 bytes), and heap poisoning (disabled) use their Kconfig defaults — no extra overrides are needed.

The sdkconfig.ci.* files add only mode-specific options (e.g. CONFIG_KASAN_NO_HALT for the all-in-one run, CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT for halt-mode pytest).

Running pytest

pytest pytest_kasan.py --target esp32c6 -v

Memory and Performance Impact

Target Shadow Memory Code Size Overhead Free Heap Impact
ESP32 ~42 KiB (internal SRAM) ~1.5-3x instrumented components ~14% of free heap
ESP32-S3 ~60 KiB ~1.5-3x ~16% of free heap
ESP32-C3 ~54 KiB ~1.5-3x ~16% of free heap
ESP32-C6 ~64 KiB ~1.5-3x ~14% of free heap

The shadow array is placed in DRAM via the DRAM_ATTR attribute on kasan_shadow_mem (mapped into dram0_data by the standard .dram1 linker mapping). On targets with PSRAM the shadow currently stays in internal SRAM; placing it in external RAM is not yet supported.