ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

funfuzz搭配Lithium实战:如何自动将巨型崩溃测试用例缩减到最小复现代码

funfuzz搭配Lithium实战:如何自动将巨型崩溃测试用例缩减到最小复现代码 funfuzz搭配Lithium实战如何自动将巨型崩溃测试用例缩减到最小复现代码【免费下载链接】funfuzzA collection of fuzzers in a harness for testing the SpiderMonkey JavaScript engine.项目地址: https://gitcode.com/gh_mirrors/fu/funfuzzfunfuzz 是 Mozilla 维护的 SpiderMonkey 模糊测试框架它能自动发现 JavaScript 引擎的崩溃并借助 Lithium 测试用例缩减器把动辄上千行的巨型崩溃测试用例压缩成几行最小复现代码让工程师能一眼看懂问题根源。本文带你完整看懂这套发现崩溃 → 自动缩减 → 验证上报的全流程。为什么巨型崩溃测试用例必须瘦身jsfunfuzz 生成器会随机吐出大量代码正则、Proxy、数学运算、递归、垃圾收集器干扰……一次真实的模糊测试输出动辄几千行、数兆字节部分用例可达 8MB。这种巨型测试用例有三个致命问题难以阅读开发者无法在几千行里定位真正触发崩溃的语句难以二分手工删除一半代码反复验证费时费力难以存储FuzzManager 提交前必须压缩否则占满空间Lithium是一个通用的测试用例缩减器核心思想简单粗暴不断删除代码整行、整块、甚至单个字符然后重新运行判断是否还崩溃——只要崩溃还在删除就保留崩溃消失了就恢复。如此迭代最终剩下的就是最小复现代码。funfuzz 把这套思想工程化源码主要在 src/funfuzz/util/lithium_helpers.py。第一步funfuzz 如何判定这里出了崩溃在缩减之前框架必须先确认当前输入确实有趣。src/funfuzz/js/js_interesting.py 定义了 6 级不满等级从最轻到最重依次是等级含义典型场景fine一切正常正常运行结束jsfunfuzz did not finish未完成确定性构建中断jsfunfuzz decided to exit主动退出检测到内部 bugoverall mismatch输出不一致JIT 对比测试差异valgrind error内存安全Valgrind 报错new assert or crash断言/崩溃段错误、ASan 报错每当主循环 src/funfuzz/js/loop.py 检测到等级达到overall mismatch及以上就会启动缩减流水线。第二步标记缩减窗口把输出变成独立文件jsfunfuzz 的输出里混杂着生成器框架代码真正用户代码被包裹在特殊注释标记中// DDBEGIN…// DDEND告诉 Lithium只需要缩减这两行之间的区域/*FRC-前缀标记哪些行来自生成器、哪些是真实测试语句loop.py 用file_manipulation.fuzzSplice把带/*FRC-的行拼接进一个独立的 jsfunfuzz 外壳生成一个可直接运行的测试文件交给 Lithium 处理。还有一个巧妙设计文件里埋着一个反向书写的NIGEBDD标记即DDBEGIN从右往左拼写它会在缩减中后期被激活为第二个缩减窗口扩大缩减范围——这正是 run-reduction-marker.js 里那句SECOND NIGEBDD的用途。核心揭秘7 步缩减策略一步比一步狠reduction_strat函数lithium_helpers.py 第 127 行起编排了 7 步递进式策略每一步都会重新运行 Lithium整文件行级缩减先大刀阔斧地删行通常能砍掉 90% 的代码整理tryItOut/countX后按 1 行步长缩减把干扰结构调整成更好删的形式✂️countX独占一行后按 2 行步长缩减再跑一轮 2 行缩减专门成对删除STRICT_MODE这类行字符级缩减--char对幸存的行继续逐字符删把语句削到最精简激活NIGEBDD第二个缩减窗口带 1 行偏移再做一轮行缩减最终行级缩减收尾确认没有可删的残留细节上有两个聪明的条件判断只有当第一步缩减后剩余不超过 50 行才会继续执行第 2~7 步小文件才值得精细化通过--maxruntime参数对应targetTime控制总时长保证模糊测试主循环不卡死第三步结果验证与自动上报缩减结束后readLithiumResult解析 Lithium 日志可能得到 4 种状态✅LITH_FINISHED缩减成功日志会打印类似Lithium result: succeeded, reduced to: 4 lines❌LITH_NO_REPRO原始用例都无法稳定复现环境或偶发问题LITH_RETESTED_STILL_INTERESTING重新测试后依然复现LITH_BUSTEDLithium 运行本身出了问题只有LITH_FINISHED时loop.py 会用缩减后的最小文件重跑一次若仍崩溃以最高质量分quality0提交 FuzzManager否则降级提交。整个缩减日志会被压缩保存为*-lith-out.txt.gz方便事后审计。彩蛋如果本地存在 mozilla 源码仓库且目标时间超过 3 小时funfuzz 还会自动接力运行 autobisectjs在提交历史中二分出是哪个提交引入的回归从最小复现直接走到罪魁祸首。实战手动运行 Lithium 缩减你已有的崩溃用例如果你手上已经有一个崩溃测试用例完全可以脱离主循环手动操作。准备环境需要 Python 3.6 和依赖git clone https://gitcode.com/gh_mirrors/fu/funfuzz cd funfuzz pip install -r requirements.txt方式一验证 jsfunfuzz 用例崩溃/断言类python -m funfuzz.js.js_interesting /path/to/knownPath /path/to/js-shell --fuzzing-safe testcase.js参数说明--minlevelLithium 认为有趣的最低等级--timeout单次运行超时秒数默认 120--valgrind用 Valgrind 包裹运行方式二验证 compare_jit 输出不一致类用例python -m funfuzz.js.compare_jit --flags--ion --fuzzing-safe --timeout10 /path/to/knownPath /path/to/js-shell testcase.jsLithium 缩减完成后日志会直接打印一条可复制的复现命令--strategycheck-only随时可以复查。快速上手检查清单⏱️ 缩短--timeout能在缩减速度和对偶发崩溃的容忍度之间取得平衡 输出不一致类 bug 建议使用确定性构建--differential-testing避免误判 保留wN-lith-out.txt.gz日志它是整个缩减过程的完整记录 缩减产物wN-reduced.js就是你要提交给工程师的最小复现文件总结funfuzz Lithium 的组合展示了模糊测试的后半程价值发现问题只是开始自动缩减到最小复现、自动定位回归提交、自动上报才是闭环。整条流水线对使用者几乎零操作——你只需要配置好 shell 和仓库路径剩下的交给 lithium_helpers.py 的 7 步策略去削铁如泥。【免费下载链接】funfuzzA collection of fuzzers in a harness for testing the SpiderMonkey JavaScript engine.项目地址: https://gitcode.com/gh_mirrors/fu/funfuzz创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表