mcpField
A
address-sanitizer

address-sanitizer

github.com/trailofbits测试与质量7.9k5.4k 次安装今天更新
代码仓库

关于 address-sanitizer

AddressSanitizer(ASan)是一种编译期插桩的内存错误检测技术,适用于软件测试和模糊测试。它提供运行时诊断,可发现越界访问、释放后使用等问题。

主要功能

  1. 01编译期插桩内存操作
  2. 02检测缓冲区溢出与释放后使用
  3. 03报告内存分配和调用栈信息
  4. 04通过 ASAN_OPTIONS 配置行为
  5. 05可与多种模糊测试器集成

适用场景

  1. 01排查 C/C++ 程序的内存错误
  2. 02测试含 unsafe 代码的 Rust 项目
  3. 03在单元测试中定位内存破坏
  4. 04分析模糊测试发现的崩溃

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/trailofbits/skills --skill address-sanitizer

安装后在 Claude Code 中输入/address-sanitizer确认已加载。

附带文件agents/openai.yamlassets/trail-of-bits-mark.svg

详细介绍

AddressSanitizer(ASan)

AddressSanitizer(ASan)是一种广泛采用的内存错误检测工具,在软件测试中,尤其是模糊测试中被大量使用。它有助于检测可能被忽略的内存损坏漏洞,例如缓冲区溢出、释放后使用错误以及其他内存安全违规。

概述

ASan 能有效识别内存漏洞,因此已成为模糊测试中的标准做法。它会在编译时对代码进行插桩,以跟踪内存分配和访问,并在运行时检测非法操作。

核心概念
概念描述
插桩ASan 会在编译期间为内存操作添加运行时检查
影子内存映射 20 TB 虚拟内存,以跟踪分配状态
性能开销与未插桩的代码相比,速度约降低 2–4 倍
检测范围可发现缓冲区溢出、释放后使用错误、重复释放和内存泄漏

适用场景

在以下场景中应用此技术:

  • 对 C/C++ 代码进行模糊测试,以查找内存安全漏洞
  • 使用 unsafe 块测试 Rust 代码
  • 调试与内存损坏有关的崩溃
  • 在怀疑存在内存错误时运行单元测试

在以下场景中跳过此技术:

  • 运行生产代码(ASan 可能会降低安全性)
  • 平台为 Windows 或 macOS(ASan 支持有限)
  • 对于你的用例,性能开销无法接受
  • 对不涉及 FFI 的纯安全语言进行模糊测试(例如纯 Go、纯 Java)

快速参考

任务命令/模式
启用 ASan(Clang/GCC)-fsanitize=address
启用详细输出ASAN_OPTIONS=verbosity=1
禁用泄漏检测ASAN_OPTIONS=detect_leaks=0
出错时强制中止ASAN_OPTIONS=abort_on_error=1
多个选项ASAN_OPTIONS=verbosity=1:abort_on_error=1

分步指南

第 1 步:使用 ASan 编译

使用 -fsanitize=address 标志编译并链接代码:

clang -fsanitize=address -g -o my_program my_program.c

建议使用 -g 标志,以便 ASan 检测到错误时提供更清晰的堆栈跟踪。

第 2 步:配置 ASan 选项

设置 ASAN_OPTIONS 环境变量以配置 ASan 的行为:

export ASAN_OPTIONS=verbosity=1:abort_on_error=1:detect_leaks=0
第 3 步:运行程序

执行经过 ASan 插桩的二进制文件。检测到内存错误时,ASan 会输出详细报告:

./my_program
第 4 步:调整模糊测试器的内存限制

ASan 需要约 20 TB 虚拟内存。请禁用模糊测试器的内存限制:

  • libFuzzer:-rss_limit_mb=0
  • AFL++:-m none

常见模式

模式:基本 ASan 集成

使用场景: 标准模糊测试设置,启用 ASan

之前:

clang -o fuzz_target fuzz_target.c
./fuzz_target

之后:

clang -fsanitize=address -g -o fuzz_target fuzz_target.c
ASAN_OPTIONS=verbosity=1:abort_on_error=1 ./fuzz_target
模式:ASan 与单元测试

使用场景: 为单元测试套件启用 ASan

之前:

gcc -o test_suite test_suite.c -lcheck
./test_suite

之后:

gcc -fsanitize=address -g -o test_suite test_suite.c -lcheck
ASAN_OPTIONS=detect_leaks=1 ./test_suite

高级用法

提示与技巧
提示作用
使用 -g 标志提供详细的堆栈跟踪,便于调试
设置 verbosity=1确认 ASan 在程序启动前已启用
在模糊测试期间禁用泄漏检测泄漏检测不会立即导致崩溃,还会使输出变得杂乱
启用 abort_on_error=1某些模糊测试器需要使用 abort() 而不是 _exit()
理解 ASan 报告

ASan 检测到内存错误时,会输出详细报告,其中包括:

  • 错误类型:缓冲区溢出、释放后使用错误等
  • 堆栈跟踪:错误发生的位置
  • 分配/释放跟踪:内存分配/释放的位置
  • 内存映射:错误周围的影子内存状态

ASan 报告示例:

==12345==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60300000eff4 at pc 0x00000048e6a3
READ of size 4 at 0x60300000eff4 thread T0
    #0 0x48e6a2 in main /path/to/file.c:42
组合使用 Sanitizer

ASan 可以与其他 Sanitizer 组合使用,以实现全面检测:

clang -fsanitize=address,undefined -g -o fuzz_target fuzz_target.c
平台注意事项

Linux:全面支持 ASan,性能最佳 macOS:支持有限,部分功能可能无法使用 Windows:支持处于实验阶段,不建议用于生产环境的模糊测试

反模式

反模式问题正确做法
在生产环境中使用 ASan可能降低应用程序的安全性仅在测试时使用 ASan
未禁用内存限制模糊测试器可能因 20TB 虚拟内存而终止进程设置 -rss_limit_mb=0 或 -m none
忽略泄漏报告内存泄漏表明资源管理存在问题在模糊测试活动结束时查看泄漏报告

工具专属指南

libFuzzer

同时使用模糊测试器和地址消毒器进行编译:

clang++ -fsanitize=fuzzer,address -g harness.cc -o fuzz

运行时不限制 RSS:

./fuzz -rss_limit_mb=0

集成提示:

  • 始终将 -fsanitize=fuzzer 与 -fsanitize=address 结合使用
  • 使用 -g 在崩溃报告中生成详细的堆栈跟踪
  • 考虑使用 ASAN_OPTIONS=abort_on_error=1,以更好地处理崩溃

参见:libFuzzer:AddressSanitizer

AFL++

使用 AFL_USE_ASAN 环境变量:

AFL_USE_ASAN=1 afl-clang-fast++ -g harness.cc -o fuzz

运行时不限制内存:

afl-fuzz -m none -i input_dir -o output_dir ./fuzz

集成提示:

  • AFL_USE_ASAN=1 会自动添加适当的编译标志
  • 使用 -m none 禁用 AFL++ 的内存限制
  • 对于覆盖率映射较大的程序,可考虑使用 AFL_MAP_SIZE

参见:AFL++:AddressSanitizer

cargo-fuzz(Rust)

使用 --sanitizer=address 标志:

cargo fuzz run fuzz_target --sanitizer=address

或在 fuzz/Cargo.toml 中配置:

[profile.release]
opt-level = 3
debug = true

集成提示:

  • ASan 适用于对不安全 Rust 代码或 FFI 边界进行模糊测试
  • 安全 Rust 代码可能无法从中获得同等程度的收益(编译器已能阻止许多错误)
  • 重点关注不安全代码块、原始指针和 C 库绑定

参见:cargo-fuzz:AddressSanitizer

honggfuzz

使用 ASan 编译并与 honggfuzz 链接:

honggfuzz -i input_dir -o output_dir -- ./fuzz_target_asan

编译目标:

hfuzz-clang -fsanitize=address -g target.c -o fuzz_target_asan

集成提示:

  • honggfuzz 开箱即可与 ASan 良好配合
  • 使用反馈驱动模式,以便在启用消毒器时获得更好的覆盖率
  • 监控内存用量,因为 ASan 会增加内存占用

故障排除

问题原因解决方案
模糊测试器立即终止进程内存限制太低,无法满足 ASan 的 20TB 虚拟内存需求使用 -rss_limit_mb=0(libFuzzer)或 -m none(AFL++)
“ASan runtime not initialized”链接顺序错误或缺少运行时确保编译和链接时都使用 -fsanitize=address
泄漏报告使输出杂乱默认启用了 LeakSanitizer设置 ASAN_OPTIONS=detect_leaks=0
性能较差(减速超过 4 倍)处于调试模式或构建未优化使用 -O2 或 -O3 与 -fsanitize=address 一起编译
ASan 未检测到明显错误二进制文件未插桩使用 ASAN_OPTIONS=verbosity=1 检查 ASan 是否打印了启动信息
误报拦截器冲突查看 ASan 常见问题解答,了解特定库的已知问题

相关技能

使用此技术的工具
技能应用方式
libfuzzer使用 -fsanitize=fuzzer,address 编译,以集成模糊测试和内存错误检测
aflpp在编译期间使用 AFL_USE_ASAN=1 环境变量
cargo-fuzz使用 --sanitizer=address 标志,为 Rust 模糊测试目标启用 ASan
honggfuzz使用 -fsanitize=address 编译目标,进行 ASan 插桩模糊测试
相关技术
技能关联
undefined-behavior-sanitizer常与 ASan 结合使用,以全面检测错误(未定义行为和内存错误)
fuzz-harness-writing测试框架必须能够处理 ASan 检测到的崩溃并避免误报
coverage-analysis覆盖率引导的模糊测试有助于触发 ASan 可检测内存错误的代码路径

资源

关键外部资源

AddressSanitizer on Google Sanitizers Wiki

官方 ASan 文档涵盖:

  • 算法与实现细节
  • 可检测错误类型的完整列表
  • 性能特征与开销
  • 平台特定行为
  • 已知限制与不兼容性

SanitizerCommonFlags

所有 Sanitizer 共用的通用配置标志:

  • verbosity:控制诊断输出级别
  • log_path:将 Sanitizer 输出重定向到文件
  • symbolize:在报告中启用/禁用符号解析
  • external_symbolizer_path:使用自定义符号化器

AddressSanitizerFlags

ASan 专用配置选项:

  • detect_leaks:控制内存泄漏检测
  • abort_on_error:出错时调用 abort() 还是 _exit()
  • detect_stack_use_after_return:检测栈上的 use-after-return 缺陷
  • check_initialization_order:查找初始化顺序缺陷

AddressSanitizer FAQ

常见陷阱与解决方案:

  • 链接顺序问题
  • 与其他工具的冲突
  • 平台特定问题
  • 性能调优技巧

Clang AddressSanitizer Documentation

Clang 专属指南:

  • 编译标志与选项
  • 与其他 Clang 特性的交互
  • 支持的平台与架构

GCC Instrumentation Options

GCC 专属 ASan 文档:

  • GCC 专属标志与行为
  • 与 Clang 实现的差异
  • GCC 中的平台支持

AddressSanitizer: A Fast Address Sanity Checker (USENIX Paper)

包含技术细节的原始研究论文:

  • 影子内存算法
  • 虚拟内存需求(历史上为 16TB,现在约 20TB)
  • 性能基准测试
  • 设计决策与权衡

评论

支持 Markdown