0

0

如何使用LLVM的sanitizers为c++项目进行模糊测试(fuzzing)? (libFuzzer)

尼克

尼克

发布时间:2026-01-18 12:14:02

|

269人浏览过

|

来源于php中文网

原创

c++kquote>必须一起链接。libFuzzer 仅生成输入并发现崩溃,而 AddressSanitizer 负责检测越界访问、UAF 等内存错误;单独使用会遗漏真实 bug 或导致不可复现崩溃。

如何使用llvm的sanitizers为c++项目进行模糊测试(fuzzing)? (libfuzzer)

libFuzzer 需要和 AddressSanitizer 一起链接吗?

必须一起链接。libFuzzer 本身不检测内存错误,它只负责生成输入、驱动目标函数、发现崩溃;而崩溃是否由越界访问、UAF 或溢出引发,得靠 ASan(AddressSanitizer)这类 sanitizer 实时拦截并报告。单独用 libFuzzer,很多真实 bug 会静默跳过或表现为不可复现的随机 crash。

典型链接方式是同时启用 -fsanitize=address,fuzzer(Clang),这会让编译器自动链接 libclang_rt.fuzzerlibclang_rt.asan。漏掉 address(或 undefinedmemory 等)会导致 sanitizer 失效,但 fuzzing 还能跑——只是你根本不知道 bug 是什么类型。

  • -fsanitize=address,fuzzer 是最常用组合;加 undefined 可捕获整数溢出、未定义行为,但会显著拖慢速度
  • 不能只写 -fsanitize=fuzzer:Clang 会报错 “fuzzer requires other sanitizer”
  • 确保所有 .o 文件(包括依赖的静态库)都用相同 sanitizer 标志编译,否则链接时可能符号冲突或运行时 ASan 不生效

如何编写一个符合 libFuzzer 要求的 fuzz target 函数?

入口函数签名必须严格为 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)。这不是约定,是 libFuzzer 的硬性 ABI 要求——它通过 dlsym 查找这个符号,拼错大小写、缺 extern "C"、参数类型不符都会导致 “no fuzz target found” 错误。

关键点不是“怎么写逻辑”,而是“怎么避免干扰 fuzzing 进程”:

立即学习C++免费学习笔记(深入)”;

  • 禁止调用 exit()abort()std::terminate() —— 应让异常传播到顶层,由 libFuzzer 捕获并记录
  • 避免全局状态累积(如 static vector push_back 不清空),否则后续输入可能因残留数据 crash,造成误报
  • 如果被测函数抛异常,确保没被中间 catch 吞掉;libFuzzer 默认能捕获未处理异常
  • 示例中常见错误:把 std::string(Data, Size) 直接传给解析函数——若 Data 含 null 字节,字符串提前截断,实际喂给 parser 的不是完整输入
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
  if (Size < 2) return 0; // 快速拒绝太短输入
  try {
    // 正确:用原始指针+长度构造 std::string_view 或直接传入解析器
    auto input = std::string_view(reinterpret_cast(Data), Size);
    my_parser(input); // 假设这是你要 fuzz 的函数
  } catch (...) {
    return 0; // 让 libFuzzer 记录这次异常
  }
  return 0;
}

为什么用 -fsanitize=fuzzer 时出现 “undefined symbol: __sanitizer_acquire_crash_state”?

这是典型的 sanitizer 运行时库链接缺失或版本不匹配。libFuzzer 依赖 Clang 自带的 sanitizer 运行时(libclang_rt.fuzzer 和配套的 asan/ubsan 库),但如果你混用了系统 GCC 工具链、旧版 Clang,或手动指定 -L 路径覆盖了默认路径,就容易触发该错误。

AI at Meta
AI at Meta

Facebook 旗下的AI研究平台

下载

排查顺序如下:

  • 确认全程使用同一套 Clang:检查 clang++ --versionclang++ -print-libgcc-file-name 输出路径是否一致
  • 不要手动加 -lclang_rt.fuzzer:Clang 在识别 -fsanitize=fuzzer 时会自动插入正确路径和库,手动加反而易出错
  • 检查是否误启用了 -static-libsan:它会把 sanitizer 打包进可执行文件,但 libFuzzer 的初始化代码可能找不到动态符号,建议先禁用
  • macOS 上还需额外加 -fsanitize=fuzzer,address -stdlib=libc++,因为系统默认 libstdc++ 不兼容 ASan

如何让 fuzz target 支持自定义字典和语料库?

libFuzzer 通过命令行参数控制语料行为,不需要改代码。字典(dictionary)用于引导变异朝特定 token(如 magic bytes、协议关键字)方向搜索;语料(corpus)是已知有效的输入集合,用来 seed 初始测试集。

核心参数组合:

  • -dict=parser.dict:字典文件每行一个 token,例如 "HTTP/""\x00\x01\x02"(十六进制需用 \x 表示)
  • ./fuzzer corpus_dir/:运行时读取 corpus_dir/ 下所有文件作为初始语料;若目录不存在,libFuzzer 会创建它并保存新发现的 crash/minimized inputs
  • -max_len=4096:限制单次输入最大长度,防止 OOM;默认 4096,对解析器类 target 常需调小(如 512)提升效率
  • -timeout=20:单次执行超时秒数,避免死循环拖垮 fuzzing 进程

注意:字典内容必须是 ASCII 可见字符或合法转义序列;二进制 token(如 JPEG SOI \xFF\xD8)必须写成 "\xff\xd8",不能用 raw bytes 写入文件,否则 libFuzzer 解析失败。

相关专题

更多
python中print函数的用法
python中print函数的用法

python中print函数的语法是“print(value1, value2, ..., sep=' ', end=' ', file=sys.stdout, flush=False)”。本专题为大家提供print相关的文章、下载、课程内容,供大家免费下载体验。

185

2023.09.27

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

318

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

231

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

436

2024.03.01

登录token无效
登录token无效

登录token无效解决方法:1、检查token的有效期限,如果token已经过期,需要重新获取一个新的token;2、检查token的签名,如果签名不正确,需要重新获取一个新的token;3、检查密钥的正确性,如果密钥不正确,需要重新获取一个新的token;4、使用HTTPS协议传输token,建议使用HTTPS协议进行传输 ;5、使用双因素认证,双因素认证可以提高账户的安全性。

6095

2023.09.14

登录token无效怎么办
登录token无效怎么办

登录token无效的解决办法有检查Token是否过期、检查Token是否正确、检查Token是否被篡改、检查Token是否与用户匹配、清除缓存或Cookie、检查网络连接和服务器状态、重新登录或请求新的Token、联系技术支持或开发人员等。本专题为大家提供token相关的文章、下载、课程内容,供大家免费下载体验。

806

2023.09.14

token怎么获取
token怎么获取

获取token值的方法:1、小程序调用“wx.login()”获取 临时登录凭证code,并回传到开发者服务器;2、开发者服务器以code换取,用户唯一标识openid和会话密钥“session_key”。想了解更详细的内容,可以阅读本专题下面的文章。

1062

2023.12.21

token什么意思
token什么意思

token是一种用于表示用户权限、记录交易信息、支付虚拟货币的数字货币。可以用来在特定的网络上进行交易,用来购买或出售特定的虚拟货币,也可以用来支付特定的服务费用。想了解更多token什么意思的相关内容可以访问本专题下面的文章。

1245

2024.03.01

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

43

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
CSS3 教程
CSS3 教程

共18课时 | 4.6万人学习

Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号