Harness 写得好不好,比选哪个 fuzzer 重要得多

经常看到有人纠结 AFL++ 还是 libFuzzer,但实际上绝大多数"fuzz 了一周没结果"的情况,问题出在 harness 上。

几条我踩过坑的经验:

1. 入口越深越好
不要从 main 开始喂文件。找到真正解析数据的那个函数,直接调它。省掉的初始化开销是几个数量级的执行速度差异。

2. 每次执行必须干净
全局状态不重置,第二次执行的行为就依赖第一次,覆盖率反馈会失真。要么每次重新初始化,要么用 fork server。

3. 别让它卡在校验和上
输入格式有 CRC 的话,fuzzer 几乎不可能随机蒙对。直接在 harness 里把校验和算好覆盖进去。这一条能救活一个完全跑不动的 fuzzing。

4. 种子语料要小而多样
一百个 2KB 的种子比十个 2MB 的好。变异的粒度和输入大小相关。

5. 先看覆盖率再谈 crash
跑一天没 crash 不代表没 bug,先用 llvm-cov 看看它到底跑到了哪些代码。很多时候你会发现它根本没进到解析逻辑里。

第 5 条我觉得最该先做——它能立刻告诉你 harness 是不是废的。