Community编程与开发github.com

ctoth/覆盖率引导的模糊测试

构建并运行带有运行时特定发现、重置和重放语义的仪器化模糊测试流水线。用于配置 AFL++、libFuzzer、Go 模糊测试、cargo-fuzz、Atheris、Jazzer、Jazzer.js(用于 Node.js/TypeScript)或 FuzzTest,或诊断现有测试活动中低效覆盖率问题。浏览器 JavaScript 在此没有覆盖率引导的路线。

覆盖率引导的模糊测试 是什么?

该技能提供了为多种编程语言和运行时环境设置和操作覆盖率引导的模糊测试的全面指导。它涵盖如何选择正确的模糊测试工具(如 AFL++、libFuzzer、Go 模糊测试、cargo-fuzz、Atheris、Jazzer、Jazzer.js 和 FuzzTest),并强调理解特定平台细节的重要性,例如正确的仪器化、状态重置和重放语义。技能指导用户进行有限的信息性试点运行,以验证目标覆盖率和 Oracle 行为,然后再将工作扩展到多个 worker。它还提供了如何解释和保留模糊测试证据的详细说明,强调保存精确的输入、配置和生命周期信息以确保可重现的故障诊断。该技能明确指出,浏览器 JavaScript 没有进程内覆盖率引导的路由,应留给处理 UI 事件序列的其他技能。它引用已建立的最佳实践和官方文档来源,使其成为在 CI/CD 环境或本地开发中设置有效模糊测试流水线的可靠参考。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ctoth/computational-bugfinding-skills-plugin/tree/HEAD/plugins/bugfinding/skills/coverage-guided-fuzzing

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

覆盖率引导的模糊测试 是做什么的?

让真实目标在反馈下执行,并带有预期的 Oracle 和可重现的生命周期。运行中的模糊测试二进制文件或增长的语料库并不表示有效的目标覆盖率:"corpus count 值是衡量覆盖质量的一个糟糕指标"(AFL++ 深入模糊测试 §3.g)。

选择实际的流水线

阅读目标入口点、构建图、已启用功能、运行时/架构、解码器和属性。识别哪些目标模块接收了仪器化,以及在模糊测试构建下发生了哪些变化;仅驱动程序的仪器化路径或仅在包装器上启用的功能可能会遗漏预期的实现。cargo-fuzz 功能选项 "控制 fuzz_targets crate" 直到被转发,而 libFuzzer 将仪器化(-fsanitize=fuzzer-no-link)与链接其 main() 分离(Rust 模糊测试书指南,Cargo 功能,LLVM libFuzzer,模糊测试用法)。

使用现有的合适生产者和构建拥有者。仅选择适用的执行参考:

目标阅读
原生源代码/二进制,AFL++ 或 libFuzzer原生运行器
Go 或 RustGo 和 Rust
Python/原生扩展或 JVMPython 和 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 页)。

关于具体的误导性运行和修正,请阅读常见错误。此技能不会产生任何新的特定于目标的框架。

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

相关技能