覆盖率引导的模糊测试 是做什么的?
让真实目标在反馈下执行,并带有预期的 Oracle 和可重现的生命周期。运行中的模糊测试二进制文件或增长的语料库并不表示有效的目标覆盖率:"corpus count 值是衡量覆盖质量的一个糟糕指标"(AFL++ 深入模糊测试 §3.g)。
选择实际的流水线
阅读目标入口点、构建图、已启用功能、运行时/架构、解码器和属性。识别哪些目标模块接收了仪器化,以及在模糊测试构建下发生了哪些变化;仅驱动程序的仪器化路径或仅在包装器上启用的功能可能会遗漏预期的实现。cargo-fuzz 功能选项 "控制 fuzz_targets crate" 直到被转发,而 libFuzzer 将仪器化(-fsanitize=fuzzer-no-link)与链接其 main() 分离(Rust 模糊测试书指南,Cargo 功能,LLVM libFuzzer,模糊测试用法)。
使用现有的合适生产者和构建拥有者。仅选择适用的执行参考:
| 目标 | 阅读 |
|---|---|
| 原生源代码/二进制,AFL++ 或 libFuzzer | 原生运行器 |
| Go 或 Rust | Go 和 Rust |
| Python/原生扩展或 JVM | Python 和 JVM |
| 带有 FuzzTest 的 C++ 属性域 | C++ FuzzTest |
| Node.js(CJS、ESM、通过 Jest 的 TypeScript) | 使用 Jazzer.js 的 Node.js |
浏览器应用程序代码没有进程内覆盖率引导的路由:Jazzer.js 将 "其他运行时或浏览器支持" 排除在范围之外(Jazzer.js 架构,约束)。将浏览器 UI 探索路由到拥有 UI 事件序列的技能。
在更改配置之前,验证所选发布版本的先决条件和已安装的帮助。参考文献记录了特定日期的源代码快照,并不保证每个版本/平台都支持相同的标志。在用户现有的权限内调用;此技能本身不授权安装、目标编辑或外部支出。
运行有限的信息性试点
在添加 worker 之前,建立发现模式、相关目标仪器化、状态重置和有效的 Oracle。Go 种子重放、Jazzer 回归、Jazzer.js Jest 回归和 FuzzTest 单元模式与其发现模式不同:纯 go test 运行种子 "很像单元测试","除非显式启用模糊测试模式,否则 Jazzer 以回归模式运行",Jazzer.js 在 Jest 下默认为 "regression",而 FuzzTest 单元模式 "在没有 sanitizer 和覆盖率仪器化的情况下运行"(Go 模糊测试,运行模糊测试,Jazzer README,回归模式,Jazzer.js 模糊测试设置,模式,FuzzTest Bazel 快速入门,创建并运行模糊测试)。
分别观察解码器准入、预期操作、成功效果和属性评估与引擎覆盖率的关系;对压缩格式的字节变异可能导致 "几乎所有生成的输入对于 uncompress 都无效"(Google 结构感知模糊测试指南,示例:压缩)。使用覆盖率、重置和反馈诊断被拒绝的格式、隐藏状态或未满足的依赖。针对已演示的阻塞器,选择字典/比较反馈或结构变异;每种方法都会改变搜索的不同部分(AFL++ CmpLog,Google 结构感知模糊测试指南)。
保持每个输入、模糊测试时间、挂钟时间、worker/CPU 和内存控制的区别;在授权范围内包含设置/重放成本。AFL++ -V 是 "(仅模糊测试时间!)",而 -E 是 "总执行次数的近似值";两者都不是聚合进程 CPU(AFL++ 选定参考 CLI 源代码,用法文本)。Go -timeout 不限制模糊测试阶段(Go 和 Rust)。使用单独拥有的输出和拥有的进程的有界清理;libFuzzer 关于确切工件路径指出 "不要为多个并行进程使用相同的路径"(LLVM libFuzzer,选项)。有关分配决策,请参考 bugfinding-campaign。
解释并保留证据
保存确切的输入/类型化参数、构建/配置/仪器化、初始状态或序列、命令/限制、原始引擎输出、目标/属性计数器和发出的重放材料。跨调用状态和生命周期差异可能使单文件重现无效:Go 要求 "模糊测试目标的状态不应在每个调用之后持久化",而 Jazzer 的默认 PER_TEST 是 "更可能无意中在模糊测试执行之间保留状态"(Go 模糊测试,建议,Jazzer 生命周期实现)。
返回实际执行的内容、观察到的属性、资源使用、候选者和遗漏项。区分发现与回归、覆盖率与语义可达性、候选失败与产品归因。使用 corpus-evolution 进行兼容的保留/交换,使用 failure-reduction 进行保留证据的最小化,使用 evidence-based-triage 进行归因。历史种子选择结果取决于其目标/调度器;Rebert 等人发现一个假设在 "最优调度下为假",却在轮询调度下再次测试。不要将其转化为通用吞吐量或产量承诺(Rebert 等人,第 864, 871, 873 页)。
关于具体的误导性运行和修正,请阅读常见错误。此技能不会产生任何新的特定于目标的框架。