Sanitizers
The sanitizers module integrates compiler-based runtime error detectors into the build. These sanitizers instrument the compiled code to detect memory errors, data races, and undefined behavior at runtime — catching bugs that static analysis and testing alone cannot find.
The use of sanitizers in CI pipelines is mandated by ADR-0002 — C as the Core Language, which requires AddressSanitizer and UndefinedBehaviorSanitizer at minimum.
Available sanitizers
Four sanitizers are available, each controlled by a CMake cache option:
| Option | Sanitizer | Detects | Default |
|---|---|---|---|
SANITIZE_ADDRESS | AddressSanitizer | Buffer overflows, use-after-free, stack overflow | OFF |
SANITIZE_MEMORY | MemorySanitizer | Reads of uninitialized memory (Clang only) | OFF |
SANITIZE_THREAD | ThreadSanitizer | Data races and deadlocks | OFF |
SANITIZE_UNDEFINED | UBSan | Undefined behavior (integer overflow, null deref) | OFF |
Address, Memory, and Thread sanitizers are mutually exclusive — they cannot be combined because they use
incompatible instrumentation strategies. Enabling more than one of these three produces a fatal configuration
error. UndefinedBehaviorSanitizer can be combined freely with any of the others, and the standard presets
generated by the scaffolding module pair it with AddressSanitizer in the asan preset.
When a sanitizer is enabled, the module verifies that the compiler and linker actually support it by running a
test with
check_linker_flag. If the sanitizer is not
supported by the current toolchain, configuration fails with a clear error message.
For Address, Memory, and Thread sanitizers the module also adds -fno-omit-frame-pointer to ensure that runtime
error reports include complete, readable stack traces. This flag is not needed for UndefinedBehaviorSanitizer,
which reports errors inline at the point they occur.
Function reference
target_enable_sanitizers
target_enable_sanitizers(<target>)
Applies the configured sanitizer flags to a target as private compile and link options. When no sanitizers are enabled, this function is a no-op — targets can call it unconditionally.
add_library(mylib src/mylib.c)
target_enable_sanitizers(mylib)
add_executable(mylib-test tests/test.c)
target_enable_sanitizers(mylib-test)
Variables defined
| Variable | Description |
|---|---|
SANITIZER_COMPILE_OPTIONS | Compiler flags for the enabled sanitizers |
SANITIZER_LINK_OPTIONS | Linker flags for the enabled sanitizers |
Usage
The scaffolding module generates presets for each sanitizer combination:
make build PRESET=asan # AddressSanitizer + UBSan
make build PRESET=tsan # ThreadSanitizer
make build PRESET=ubsan # UBSan only