Files
libaaruformat/docs/ASAN_USAGE.md

9.5 KiB

Address Sanitizer (ASan) Usage Guide

Overview

Address Sanitizer (ASan) is a fast memory error detector that helps identify:

  • Buffer overflows (heap, stack, and global)
  • Use-after-free bugs
  • Use-after-return bugs
  • Use-after-scope bugs
  • Double-free bugs
  • Memory leaks
  • Invalid pointer operations

This guide explains how to build and test libaaruformat with Address Sanitizer enabled.

Prerequisites

Compiler Support

Address Sanitizer requires a modern compiler:

  • GCC: Version 4.8 or later
  • Clang: Version 3.1 or later
  • MSVC: Version 16.9 or later (Visual Studio 2019 16.9+)

Platform Support

ASan is supported on:

  • Linux (x86_64, ARM, AArch64)
  • macOS (x86_64, ARM64)
  • Windows (x86_64, ARM64)

Building with Address Sanitizer

Option 1: Using CMake Command Line

Build the library and tests with ASan enabled:

# Create a separate build directory for ASan builds
mkdir build-asan
cd build-asan

# Configure with ASan enabled
cmake -DUSE_ASAN=ON ..

# Build the library and tests
cmake --build .

Option 2: Using CMake with Build Type

For additional debug information (recommended):

mkdir build-asan
cd build-asan

# Configure with ASan and Debug build type
cmake -DUSE_ASAN=ON -DCMAKE_BUILD_TYPE=Debug ..

# Build
cmake --build .

Option 3: Cross-Platform Build Script

For convenience, use the provided build script:

# On Linux/macOS
./build.sh -DUSE_ASAN=ON -DCMAKE_BUILD_TYPE=Debug

# On Windows (PowerShell)
cmake -DUSE_ASAN=ON -DCMAKE_BUILD_TYPE=Debug -B build-asan -S .
cmake --build build-asan

Running Tests with Address Sanitizer

Basic Test Execution

Once built with ASan, run the tests normally:

cd build-asan
ctest --verbose

Or run the test executable directly:

cd build-asan/tests
./tests_run

Understanding ASan Output

When ASan detects an error, it will print a detailed report including:

  1. Error type: e.g., "heap-buffer-overflow", "use-after-free"
  2. Stack trace: Shows where the error occurred
  3. Memory allocation context: Shows where the problematic memory was allocated
  4. Shadow byte legend: Explains the memory state

Example ASan error output:

=================================================================
==12345==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000014 at pc 0x000000400d3c bp 0x7fff5fbff7f0 sp 0x7fff5fbff7e8
READ of size 4 at 0x602000000014 thread T0
    #0 0x400d3b in main example.c:5
    #1 0x7ffff7a05b44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
    #2 0x400c48 in _start (a.out+0x400c48)

0x602000000014 is located 0 bytes to the right of 4-byte region [0x602000000010,0x602000000014)
allocated by thread T0 here:
    #0 0x7ffff7aaecf8 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xd9cf8)
    #1 0x400d06 in main example.c:4
    #2 0x7ffff7a05b44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
=================================================================

Environment Variables

ASan behavior can be customized using the ASAN_OPTIONS environment variable:

Detect Memory Leaks

# Enable leak detection (default on Linux, not on macOS by default)
export ASAN_OPTIONS=detect_leaks=1
./tests_run

Continue After First Error

# By default, ASan stops after the first error. To continue:
export ASAN_OPTIONS=halt_on_error=0
./tests_run

Save Error Reports to File

# Save ASan reports to files instead of stderr
export ASAN_OPTIONS=log_path=/tmp/asan.log
./tests_run
# Reports will be saved as /tmp/asan.log.12345 (with PID)

Combine Multiple Options

export ASAN_OPTIONS=detect_leaks=1:log_path=/tmp/asan.log:halt_on_error=0
./tests_run

Useful Options Summary

Option Description Default
detect_leaks=1 Enable memory leak detection 1 (Linux), 0 (macOS)
halt_on_error=0 Continue after first error 1
log_path=path Save reports to files stderr
verbosity=1 Increase verbosity level 0
symbolize=1 Symbolize stack traces 1
abort_on_error=1 Call abort() on error 0
print_stats=1 Print statistics at exit 0

Platform-Specific Notes

Linux

ASan works out of the box on most Linux distributions. Make sure you have debug symbols installed for better stack traces:

# Ubuntu/Debian
sudo apt-get install binutils

# Fedora/RHEL
sudo dnf install binutils

macOS

Important Note: Leak detection (detect_leaks=1) is not supported on macOS. If you try to enable it, ASan will abort with an error: AddressSanitizer: detect_leaks is not supported on this platform.

On macOS, use ASan options without leak detection:

# Correct for macOS
export ASAN_OPTIONS="print_stats=1:color=always"

# WRONG - will cause abort on macOS
export ASAN_OPTIONS="detect_leaks=1"  # Don't use this!

For better symbolization on macOS:

# Install llvm-symbolizer if using Clang
brew install llvm
export PATH="/usr/local/opt/llvm/bin:$PATH"

System Integrity Protection (SIP) does not need to be disabled for basic ASan functionality.

Windows (MSVC)

On Windows with MSVC, ASan requires:

  1. Visual Studio 2019 version 16.9 or later
  2. The "C++ AddressSanitizer" component installed

Additional MSVC-specific considerations:

REM Run tests in Command Prompt or PowerShell
cd build-asan\tests
.\tests_run.exe

REM For better symbols, ensure PDB files are generated
cmake -DUSE_ASAN=ON -DCMAKE_BUILD_TYPE=Debug ..

Common Issues and Solutions

Issue: False Positives

Problem: ASan reports errors in third-party libraries you can't fix.

Solution: Use suppressions file:

  1. Create a file asan_suppressions.txt:

    # Suppress leak in third-party library
    leak:libthirdparty.so
    
  2. Set the suppressions file:

    export ASAN_OPTIONS=suppressions=./asan_suppressions.txt
    ./tests_run
    

Issue: Performance Impact

Problem: Tests run significantly slower with ASan.

Solution: This is expected. ASan typically adds 2x-3x overhead. Use ASan builds only for debugging, not production.

Issue: Out of Memory

Problem: ASan uses significant additional memory (2x-3x normal).

Solution:

  • Run fewer tests in parallel
  • Increase system swap space if needed
  • Test in smaller batches

Issue: Missing Stack Traces

Problem: Stack traces show addresses but no symbols.

Solution:

  • Build with debug symbols: -DCMAKE_BUILD_TYPE=Debug
  • Install llvm-symbolizer and ensure it's in PATH
  • On Linux: Install debug packages for system libraries

Integration with CI/CD

GitHub Actions Example

name: ASan Tests

on: [push, pull_request]

jobs:
  asan:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2

    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install -y cmake build-essential

    - name: Build with ASan
      run: |
        mkdir build-asan
        cd build-asan
        cmake -DUSE_ASAN=ON -DCMAKE_BUILD_TYPE=Debug ..
        cmake --build .

    - name: Run tests with ASan
      run: |
        cd build-asan
        export ASAN_OPTIONS=detect_leaks=1:halt_on_error=1
        ctest --verbose

GitLab CI Example

asan-tests:
  stage: test
  script:
    - mkdir build-asan && cd build-asan
    - cmake -DUSE_ASAN=ON -DCMAKE_BUILD_TYPE=Debug ..
    - cmake --build .
    - export ASAN_OPTIONS=detect_leaks=1:halt_on_error=1
    - ctest --verbose
  artifacts:
    when: on_failure
    paths:
      - build-asan/Testing/Temporary/LastTest.log

Best Practices

  1. Regular Testing: Run ASan builds regularly, not just when debugging
  2. Separate Build Directory: Always use a separate build directory for ASan builds
  3. Debug Mode: Combine ASan with Debug build type for maximum information
  4. Clean Environment: Test with a clean environment to avoid interference
  5. Document Suppressions: If you use suppressions, document why each one is needed
  6. CI Integration: Add ASan tests to your CI pipeline for continuous validation

Additional Resources

Quick Reference

Build Commands

# Standard ASan build
cmake -DUSE_ASAN=ON -B build-asan -S .
cmake --build build-asan

# ASan build with debug symbols
cmake -DUSE_ASAN=ON -DCMAKE_BUILD_TYPE=Debug -B build-asan -S .
cmake --build build-asan

# Run tests
cd build-asan && ctest --verbose

Environment Variables

# Enable all leak detection
export ASAN_OPTIONS=detect_leaks=1

# Save reports to files
export ASAN_OPTIONS=log_path=/tmp/asan.log

# Multiple options
export ASAN_OPTIONS=detect_leaks=1:log_path=/tmp/asan.log:halt_on_error=0

Troubleshooting

If you encounter issues:

  1. Check compiler version supports ASan
  2. Verify CMake found the correct compiler
  3. Look for conflicting compiler flags
  4. Check environment variables aren't interfering
  5. Try with a minimal test case first
  6. Review ASan documentation for your specific platform

For project-specific issues, please file a bug report with:

  • Platform and compiler version
  • Full CMake configuration output
  • Complete ASan error report
  • Steps to reproduce