news 2026/10/12 2:13:09

ClusterFuzz 深度解析:Google 开源的可扩展分布式模糊测试基础设施

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ClusterFuzz 深度解析:Google 开源的可扩展分布式模糊测试基础设施
  • 应用安全
  • 后端
  • 开发工具

【免费下载链接】clusterfuzz

Scalable fuzzing infrastructure.

项目地址:https://gitcode.com/gh_mirrors/cl/clusterfuzz
点击查看免费下载

ClusterFuzz 是 Google 开源的可扩展模糊测试(fuzzing)基础设施,用于在软件中自动发现安全与稳定性问题,并已作为 OSS-Fuzz 的模糊测试后端运行在数万台虚拟机之上。本文以仓库根目录 README.md 为主线,结合src/clusterfuzz下的源码实现、cron 调度配置与测试用例,系统讲解其核心功能、崩溃去重算法、自动化 Bug 生命周期、多引擎接入方式与部署形态,帮助你理解并复用这套业界规模的分布式模糊测试体系。

ClusterFuzz 是什么

ClusterFuzz 是一个可扩展的模糊测试基础设施(Scalable Fuzzing Infrastructure)。它的定位不是某个单一的 fuzzer,而是把「模糊测试」这件事工程化、平台化、自动化:从大规模调度 fuzzer 运行、收集崩溃,到去重、最小化、回归定位、自动提交 Bug、跟踪修复闭环,全部流水线化。

从 README.md 可知:

  • Google 使用 ClusterFuzz 模糊测试其所有产品,并作为 OSS-Fuzz 的模糊测试后端;
  • 它具备高度可扩展性,可以运行在任意规模的集群上(例如 OSS-Fuzz 实例运行在 100,000 台虚拟机上);
  • 截至 2023 年 2 月,ClusterFuzz 已在 Google(如 Chrome)中发现约27,000个 Bug;同时帮助 OSS-Fuzz 集成的850个项目发现并修复了8,900多个安全漏洞和28,000多个 Bug。

注:上述战绩数据均来自 README 原文,属项目自述事实,引用时请注明时间口径(2023 年 2 月)。

核心功能清单:从发现到闭环

README 列举了 ClusterFuzz 帮助软件项目无缝集成模糊测试的系列能力,这也是理解其价值主张的最佳入口:

功能说明
高度可扩展可运行在任意规模集群上(如 OSS-Fuzz 的 100,000 VM 实例)
崩溃精确去重对海量崩溃做准确去重(详见下文去重算法)
全自动 Bug 处理面向多种 issue tracker(如 Monorail、Jira)自动提交、分流(triage)与关闭 Bug
多覆盖引导引擎支持 libFuzzer、AFL、AFL++、Honggfuzz,并支持集成式模糊测试(ensemble fuzzing)与模糊测试策略(fuzzing strategies)
黑盒模糊测试支持 blackbox fuzzing(无需插桩的输入生成型模糊测试)
用例最小化自动将崩溃复现用例最小化
回归定位通过二分(bisection)找出引入回归的版本区间
统计分析提供分析 fuzzer 性能与崩溃率的统计能力
Web 界面提供易用的管理界面,用于管理和查看崩溃
多认证方式支持基于 Firebase 的多种认证提供方

这些能力并非 README 中的空头承诺,而是仓库中真实存在、可逐行验证的实现。下面逐一深入。

系统架构与一次完整 Fuzz 任务的生命周期

组件划分

从仓库顶层结构看,ClusterFuzz 主要由三大部分组成:

  • src/clusterfuzz/_internal/bot:运行在各台机器(bot)上的任务执行端,负责实际运行 fuzzer、最小化、回归等;
  • src/clusterfuzz/_internal/cron:周期性的调度与后台任务(调度 fuzz、分组、triage、覆盖率等);
  • src/appengine:Web 界面与 API 层,用于管理、查看崩溃。

Fuzz 任务的执行链路

一次 fuzz 任务的核心实现位于 src/clusterfuzz/_internal/bot/tasks/utasks/fuzz_task.py。从源码结构可以梳理出关键环节:

  1. 准备:构建环境(build setup)、数据包(data bundle)、fuzz target 准备;
  2. 运行:通过统一的引擎接口调用具体 fuzzer(libFuzzer / AFL / Honggfuzz 等),详见下文「引擎抽象」;
  3. 崩溃收集:解析 fuzzer 输出,抽取崩溃栈(unsymbolized_crash_stacktrace),交给 stack_analyzer 生成crash_type、crash_state、crash_address等结构化字段(见Crash.__init__中stack_analyzer.get_crash_data(...)的调用);
  4. 安全性判定:通过 crash_analyzer.py 的is_security_issue判断是否安全漏洞,并用ignore_stacktrace过滤误报;
  5. 可复现性验证:find_main_crash调用testcase_manager.test_for_reproducibility逐一验证崩溃是否可复现,区分「可复现」与「一次性崩溃(one-time crasher)」;
  6. 上传与归档:archive_testcase_in_blobstore将 testcase 连同依赖归档到 GCS/blobstore;
  7. 创建 Testcase 实体:以(crash_type, crash_state, security_flag)为 key 分组的CrashGroup,决定是否创建新 testcase。

崩溃是否值得入库有一套校验逻辑(Crash.get_error):可被FILTER_FUNCTIONAL_BUGS过滤的非安全问题、误报(false crash)、无法存储的用例、空 crash state/type 都会被拒绝。

崩溃后处理任务链

testcase 创建后,后续任务由 src/clusterfuzz/_internal/bot/tasks/task_creation.py 按需串联,形成一条自动化流水线:

  • minimize:用例最小化;
  • regression / progression:回归区间定位与修复确认;
  • impact / blame:影响面评估与嫌疑提交定位(Chromium 项目专用,见 blame_task.py,其中通过解析 DEPS 文件计算依赖 roll,交给 Predator 服务);
  • variant:跨 job 的变体分析;
  • symbolize:符号化。

任务间还具备「flaky(不稳定复现)」处理机制:mark_unreproducible_if_flaky会先标记potentially_flaky,若第二次仍不稳定则将 testcase 标记为one_time_crasher_flag = True并设置为不可复现。

崩溃去重:精确分组的算法内核

「精确去重」是 README 强调的核心卖点。其底层实现在 src/clusterfuzz/_internal/crash_analysis/crash_comparer.py 的CrashComparer类中,结合了三种技术:

  1. 完全相等快速通道:两个 crash state 完全相同直接判定相似;
  2. 最长公共子序列(LCS):longest_common_subsequence统计两个 crash state 中按顺序相同的帧数,SAME_FRAMES_THRESHOLD = 2(默认)即认为相似;
  3. Levenshtein 编辑距离:逐行计算相似度比率(len1 + len2 - distance) / (len1 + len2),取平均后与COMPARE_THRESHOLD = 0.8(默认)比较。

此外还有两个细节值得注意:

  • 若 crash state 中含有FuzzerHash=(fuzzer 哈希串),则走精确匹配逻辑,相等才判相似(源码注释明确说明);
  • 对Missing-library、Out-of-memory、Timeout等CRASH_TYPES_WITH_UNIQUE_STATE类型(定义见 src/clusterfuzz/_internal/datastore/data_types.py),只要求 crash type 与 crash state 完全一致,不使用相似度算法。

分组器(Grouper)的聚合规则

CrashComparer只是「两两比较」的原子操作,真正的分组发生在 src/clusterfuzz/_internal/cron/grouper.py 的group_testcases()中,按顺序执行四类分组规则:

  1. 相似崩溃状态分组(_group_testcases_with_similar_states):安全漏洞只看 crash state 相似度,非安全漏洞要求 state 与 type 都相似;
  2. 同一底层 Issue 分组(_group_testcases_with_same_issues):若两个 testcase 关联同一 issue id 则合并;
  3. 变体分析分组(_group_testcases_based_on_variants):对不同 job type 下的相同变体(crash_type、crash_state、security_flag完全一致)分组,但会跳过 OOM/Timeout 等类型、NULL状态、不可复现用例、以及 top crash;
  4. 超大组收缩(_shrink_large_groups_if_needed):超过group_max_limit(默认 25,可通过项目配置deduplication.group_max_limit调整)的组,会按「可复现性 + 是否有关联 issue」加权排序,删除或关闭超出的 testcase。

分组完成后由 group_leader.py 选出每个组的 leader 作为代表。整个分组过程还通过TestcaseGroupingEvent记录每次合并原因(SIMILAR_CRASH、SAME_ISSUE、IDENTICAL_VARIANT、GROUP_MERGE等),可回溯审计。

多引擎接入:统一的 Fuzzing 引擎抽象

README 提到支持 libFuzzer、AFL、AFL++、Honggfuzz 等多个覆盖引导引擎。在仓库中,这是通过统一的引擎接口实现的:src/clusterfuzz/fuzz/engine.py 定义了Engine基类与register(name, engine_class)/get(name)注册表机制。

Engine接口的核心方法:

方法职责
prepare(corpus_dir, target_path, build_dir)生成FuzzOptions,准备一次 fuzz 会话
fuzz(target_path, options, reproducers_dir, max_time)运行模糊测试会话,返回FuzzResult(含崩溃列表与统计)
reproduce(target_path, input_path, arguments, max_time)用给定输入复现崩溃
minimize_corpus(...)/minimize_testcase(...)语料库最小化 / 用例最小化
cleanse(...)清洗用例(用垃圾数据替换非关键字节)

各引擎实现位于 src/clusterfuzz/_internal/bot/fuzzers 下,包括libFuzzer/、afl/、honggfuzz/、centipede/、googlefuzztest/等子目录。

以 libFuzzer 为例,src/clusterfuzz/_internal/bot/fuzzers/libfuzzer.py 中的LibFuzzerCommon提供了完整操作集:

  • fuzz(...):组装-max_total_time、-print_final_stats=1、-artifact_prefix等参数并执行;若启用 fork 模式(-fork),会额外预留LIBFUZZER_FORK_MODE_CLEAN_EXIT_TIME = 100.0秒的退出窗口;
  • merge(...):语料库合并,支持-merge_control_file;
  • minimize_crash(...)/cleanse_crash(...):分别对应-minimize_crash与-cleanse_crash,并用-exact_artifact_path指定输出;
  • 还针对 Android(AndroidLibFuzzerRunner,通过 adb 推送语料)、Fuchsia(FuchsiaUndercoatLibFuzzerRunner)、沙箱(MinijailLibFuzzerRunner)提供了平台特化实现。

崩溃输出中的 testcase 路径通过CRASH_TESTCASE_REGEX = r'.*Test unit written to\s*(.*(crash|oom|timeout|leak)-.*)'从日志中提取(见 libfuzzer.py)。

Fuzzing 策略与集成式模糊测试(Ensemble Fuzzing)

README 中提到的「fuzzing strategies」与「ensemble fuzzing」是提升模糊测试效果的关键机制,其定义位于 src/clusterfuzz/_internal/fuzzing/strategy.py:

CORPUS_MUTATION_RADAMSA_STRATEGY = Strategy(name='corpus_mutations_radamsa', probability=0.15, ...) CORPUS_SUBSET_STRATEGY = Strategy(name='corpus_subset', probability=0.50, manually_enable=True) FORK_STRATEGY = Strategy(name='fork', probability=0.50, ...) RANDOM_MAX_LENGTH_STRATEGY = Strategy(name='random_max_len', probability=0.15, ...) VALUE_PROFILE_STRATEGY = Strategy(name='value_profile', probability=0.33, ...) USE_EXTRA_SANITIZERS_STRATEGY = Strategy(name='extra_sanitizers', probability=0.10, ...)

Strategy是(name, probability, manually_enable)三元组,其中manually_enable=True表示该策略不参与多臂老虎机(multi-armed bandit)的概率选择流程,而是单独考虑(例如corpus_subset只有在目标支持时才启用,且应被重度使用)。libFuzzer 与 AFL 各自维护独立的策略列表(LIBFUZZER_STRATEGY_LIST/AFL_STRATEGY_LIST)。

策略池的生成在 src/clusterfuzz/_internal/bot/fuzzers/strategy_selection.py 中:

  • generate_default_strategy_pool:按各策略概率独立决定是否加入策略池,radamsa 生成器与无生成器互斥;
  • generate_weighted_strategy_pool:当环境中存在STRATEGY_SELECTION_DISTRIBUTION且选择方法非default时,按多臂老虎机实验得出的概率分布做加权随机选择;否则回退到默认方法;
  • 环境变量DISABLED_STRATEGIES(逗号分隔)可在运行时禁用指定策略。

策略的概率分布由 cron 任务 src/clusterfuzz/_internal/cron/fuzz_strategy_selection.py 定期更新,其调度配置见 configs/test/k8s/fuzz-strategy-selection.yaml。

自动化 Bug 生命周期:提交、分流与关闭

README 宣称「Fully automatic bug filing, triage and closing for various issue trackers (e.g. Monorail, Jira)」。这一能力在仓库中由 src/clusterfuzz/_internal/issue_management 与 src/clusterfuzz/_internal/cron/triage.py 共同实现。

Issue Tracker 抽象

issue_management目录下提供了统一的 tracker 抽象:

  • monorail/:Monorail(Chromium 等使用的 Google Issue Tracker)实现;
  • jira/:Jira 实现;
  • oss_fuzz_github.py:OSS-Fuzz 项目使用的 GitHub Issues 实现;
  • 基类与策略在 issue_tracker.py、issue_tracker_policy.py。

这种抽象使得同一套 triage/filing 逻辑可以对接不同 issue 系统,配置方式见 configs/test/issue_trackers/config.yaml。

自动提交(Issue Filing)

src/clusterfuzz/_internal/issue_management/issue_filer.py 负责将崩溃转化为 issue:

  • 为栈帧打标签:MEMORY_TOOLS_LABELS将 AddressSanitizer、LeakSanitizer、MemorySanitizer、ThreadSanitizer、UndefinedBehaviorSanitizer 及 afl/libfuzzer 等 token 映射为对应 issue 标签;
  • 通过platform_substitution等规则做平台化文案替换;
  • 定义NON_CRASH_TYPES(Data race、Direct-leak、Integer-overflow 等),用于决定优先级与处理策略。

定时分流(Triage)

src/clusterfuzz/_internal/cron/triage.py 的 cron 任务负责:

  • 对未关联 issue 的 testcase 判定是否需要提交 Bug(默认每项目每 24 小时最多 100 个 Bug:MAX_BUGS_PER_PROJECT_PER_24HRS_DEFAULT);
  • 对 OOM、Stack-overflow、Timeout 等类型的不可复现崩溃忽略提交;
  • 通过_add_triage_message记录 triage 结论,避免重复操作;
  • 结合分组结果,让同一组的代表 testcase 去关联同一个 issue。

配合 grouper.py 的分组,整体形成了「崩溃 → 去重分组 → 自动提交 → 关联 issue → 修复后自动关闭」的闭环。

统计、覆盖率与 Web 界面

统计能力

README 提到「Statistics for analyzing fuzzer performance, and crash rates」。相关实现集中在 src/clusterfuzz/_internal/metrics:

  • fuzzer_stats.py 与 fuzzer_stats_schema.py:解析 fuzzer 输出的统计(exec/sec、cov 等)并入库;
  • crash_stats.py:崩溃率统计,配合 BigQuery 构建报表;
  • 定时聚合由 src/clusterfuzz/_internal/cron/aggregate_fuzzer_stats.py 执行,BigQuery 数据集配置见 configs/test/bigquery/datasets.yaml。

代码覆盖率

覆盖率信息由 src/clusterfuzz/_internal/cron/fuzzer_coverage.py 定期从 GCS 拉取latest_report_infoJSON 并写入CoverageInformation实体,供 Web 界面展示每个 fuzz target 或项目的覆盖率趋势。

Web 管理界面

Web 层位于 src/appengine:handlers/提供 REST/页面 handler(testcase 详情、崩溃统计、覆盖率报表、fuzzers/jobs 管理、上传 testcase 等),前端由 src/appengine/private 下的 Polymer 组件与模板构成。认证方面支持多种提供方,README 明确说明基于 Firebase(对应auth相关 handler 与 configs/test/gae/auth.yaml)。

运行、部署与生态扩展

本地运行

仓库根目录提供统一的入口脚本 butler.py,本地开发/测试可通过python butler.py系列子命令(run_server、run_bot、run等)拉起 App Engine 模拟器与 bot,具体步骤参见 docs/getting-started/local_instance.md 与 docs/getting-started/getting_started.md。

生产部署形态

  • Docker 镜像:docker/ 目录为各角色(base、chromium、oss-fuzz、ci、fuchsia 等)提供容器化构建;

  • GCE 集群:configs/test/gce/clusters.yaml 定义集群;

  • Kubernetes 调度:configs/test/k8s/ 下的 cron job 配置展示了各调度任务,例如:

    • schedule-fuzz.yaml:run_cron.py schedule_fuzz,为各 job 创建 fuzz 任务;
    • schedule-progression-tasks.yaml:schedule_progression_tasks;
    • schedule-corpus-pruning.yaml:schedule_corpus_pruning,语料库剪枝;
    • fuzz-strategy-selection.yaml:fuzz_strategy_selection,更新策略概率分布;
    • load-bigquery-stats.yaml、sync-admins.yaml 等。

    这些 cron 任务的实现均在 src/clusterfuzz/_internal/cron 下(schedule_fuzz.py、schedule_corpus_pruning.py、schedule_progression_tasks.py、fuzz_strategy_selection.py等),并通过 src/python/bot/startup/run_cron.py 统一启动。

语料库管理

语料库通过 src/clusterfuzz/_internal/fuzzing/corpus_manager.py 与 GCS 同步:支持 zip 打包、按 SHA1 重命名去重(rename_file_to_sha)、Windows 非法文件名清洗(legalize_filenames)、gsutil rsync容错(忽略NotFoundException等可容忍错误)。公开备份(public时间戳)用于跨项目共享。

轻量版:ClusterFuzzLite

README 同时指出:如需在 CI/CD 系统上运行更轻量的版本,可参考 ClusterFuzzLite。它适合资源受限、需要把模糊测试嵌入持续集成的场景,而完整版 ClusterFuzz 面向大规模、长时运行的分布式模糊测试。

获取帮助与保持更新

  • 提问与反馈:可通过 GitHub Issues 提交问题、请求功能或寻求帮助(README 明确说明);
  • 发布公告:ClusterFuzz 的重大更新通过clusterfuzz-announce邮件组发布,如需跟踪版本演进可订阅该渠道。

总结

ClusterFuzz 的工程价值在于把「模糊测试」从单个工具升级为自动化闭环平台:用统一的引擎抽象接入 libFuzzer/AFL/Honggfuzz 等覆盖引导引擎与黑盒 fuzzer,用CrashComparer(LCS + Levenshtein)与 Grouper 实现大规模崩溃去重,用 issue tracker 抽象自动完成 Bug 的提交、分流与关闭,再辅以最小化、二分回归、统计与覆盖率、Web 界面与 Firebase 认证,形成一套可运行于万级虚拟机集群的完整解决方案。对希望自建或理解大规模模糊测试平台的技术团队而言,README.md 是入口,而src/clusterfuzz/_internal下的源码则是最佳的实现教材。

  • 应用安全
  • 后端
  • 开发工具

【免费下载链接】clusterfuzz

Scalable fuzzing infrastructure.

项目地址:https://gitcode.com/gh_mirrors/cl/clusterfuzz
点击查看免费下载

相关推荐

上一篇:ncmdump 免费 NCM 转 MP3:3 步拖拽转换,批量处理整库音乐
下一篇:一条命令把"改不动"的 STL 网格变成可编辑的 STEP 实体:stltostp 转换完整指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 2:11:10

Leaf 框架核心概念解读:Layer 与 Network 的术语体系与源码实现

机器学习深度学习 【免费下载链接】leaf Open Machine Intelligence Framework for Hackers. (GPU/CPU) 项目地址: https://gitcode.com/gh_mirrors/le/leaf 点击查看 免费下载 本指南围绕 Leaf(Open Machine Intelligence Framework for Hackers&#…

作者头像 李华
网站建设 2026/10/12 2:10:38

MySQL数据库课程设计:机票预订系统表结构设计与并发控制实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/12 2:10:15

ESP32-C3高压电容放电闹钟设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/12 2:09:15

InterviewGuide 堆排序实战:从堆原理到 C++ 手撕代码与 Top K 高频考题

教程 【免费下载链接】InterviewGuide 🔥🔥「InterviewGuide」是阿秀从校园->职场多年计算机自学过程的记录以及学弟学妹们计算机校招&秋招经验总结文章的汇总,包括但不限于C/C 、Golang、JavaScript、Vue、操作系统、数据结构、计算机…

作者头像 李华