andersch.dev

<2024-06-17 Mon>

Address Sanitization (ASan)

Address Sanitization - as performed by a tool such as AddressSanitizer (ASan) - is a method for runtime memory error detection. It tries to detect invalid memory accesses, such as the ones caused by out-of-bounds array indices or use-after-free. It is a compiler feature in clang (LLVM) and GCC.

It can be enabled with the compiler flag -fsanitize=address. To get nicer stack traces in error messages add -fno-omit-frame-pointer.

Its scope of error detection includes:

Integrating ASan

ASan supports user-set poisoned memory addresses. To use asan_poison_memory_region(addr, size) only when compiling with enabled ASan, use the following preprocessor code:

#if defined(_MSC_VER)
  #if defined(__SANITIZE_ADDRESS__)
    #define ASAN_ENABLED 1
    #define NO_ASAN __declspec(no_sanitize_address)
  #else
    #define NO_ASAN
  #endif
#elif defined(__clang__)
  #if defined(__has_feature)
    #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
      #define ASAN_ENABLED 1
    #endif
  #endif
  #define NO_ASAN __attribute__((no_sanitize("address")))
#else
  #warning "NO_ASAN is not defined for this compiler."
#endif

#if defined(__cplusplus)
  #define C_LINKAGE extern "C"
#else
  #define C_LINKAGE
#endif

#if ASAN_ENABLED
  #if defined(_WIN32)
    #pragma comment(lib, "clang_rt.asan-x86_64.lib")
  #endif
  C_LINKAGE void __asan_poison_memory_region(void const volatile *addr, size_t size);
  C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
  #define asan_poison_memory_region(addr, size)   __asan_poison_memory_region((addr), (size))
  #define asan_unpoison_memory_region(addr, size) __asan_unpoison_memory_region((addr), (size))
#else
  #define asan_poison_memory_region(addr, size)   ((void)(addr), (void)(size))
  #define asan_unpoison_memory_region(addr, size) ((void)(addr), (void)(size))
#endif

Resources