如何用 @react-doctor/fuzz 对单条规则做对抗性模糊测试?
发布时间:2026/9/15 12:42:12 锦皓数字建站

如何用 react-doctor/fuzz 对单条规则做对抗性模糊测试【免费下载链接】react-doctorYour agent writes bad React. This catches it项目地址: https://gitcode.com/GitHub_Trending/re/react-doctorreact-doctor/fuzz是 react-doctor 仓库内的对抗性模糊测试框架fuzzing harness它每一轮迭代都从语法规则、病态结构或真实语料中生成/取用一个 React/TSX 程序对它做变异然后让目标规则跑一遍用三个判定器oracle检查规则是否崩溃、是否病态地慢、是否依赖了与本意无关的源码形态。当你改动了某条规则的解析或判定逻辑、想确认它在“能解析但写得很怪”的程序上依然稳定时这就是对应的验证工具。本文只覆盖一件事对单条规则跑模糊测试读懂运行结果并复现发现的用例。前提条件在仓库检出checkout内操作react-doctor/fuzz是私有包不发布packages/fuzz/README.md 明确标注 “Private — never published”无法通过包管理器安装使用。Node^20.19.0 || 22.13.0、pnpm8仓库packageManager固定为pnpm10.29.1见根目录 package.json 的engines字段。在仓库根目录执行pnpm install安装 workspace 依赖react-doctor/fuzz通过workspace:*依赖 oxlint-plugin-react-doctor 的规则实现。完整 fuzz 是默认关闭的pnpm fuzz会显式设置REACT_DOCTOR_FUZZ1不带该变量时pnpm test只跑常开的 smoke 测试包括“100 个种子程序必须全部能解析”的生成器健康检查packages/fuzz/package.json、packages/fuzz/tests/fuzz-rules.test.ts。选定单条规则FUZZ_RULE 按子串匹配规则 id 来自规则注册表 rule-registry.ts 导出的reactDoctorRules。FUZZ_RULE的匹配逻辑是“精确相等或包含子串”fuzz-rules.test.ts 中entry.id ruleFilter || entry.id.includes(ruleFilter)所以可以传完整 id也可以传 id 的一段# 对单条规则做模糊测试在仓库根目录执行 FUZZ_RULEno-array-index-as-key pnpm fuzz注意如果FUZZ_RULE或FUZZ_TAG匹配不到任何规则测试会显式失败并输出match no registry rule — nothing was fuzzed而不是静默跑 0 条规则。仓库自带的 README 示例用的就是no-array-index-as-key这个规则 id。运行单条规则模糊测试FUZZ_RULEno-array-index-as-key pnpm fuzz这条命令的展开路径是根目录fuzz脚本 →pnpm --filter react-doctor/fuzz fuzz→cross-env REACT_DOCTOR_FUZZ1 vp test run tests/fuzz-rules.test.ts最终只会生成一个名为survives fuzzing: no-array-index-as-key的测试用例注册表中其他规则被过滤掉。运行行为的几个关键事实来自 fuzz-rules.test.ts 与 constants.ts默认 25 轮迭代、种子为 1DEFAULT_FUZZ_ITERATIONS/DEFAULT_FUZZ_SEED。每轮从三类来源取程序语法生成snippet 池提炼自真实语料、病态结构约 12% 的迭代深 JSX 嵌套、长链式等用于探测递归遍历器、语料文件仅在你提供FUZZ_CORPUS_DIR时约占 50% 的迭代。程序会被变异删除/复制/交换字符片段与整行、unicode/token 注入、拼入规则触发 token文件名在每轮轮换以覆盖路径门控test-noise 跳过、app//pages/、.client.tsx、e2e 后缀等。当某个程序让规则FIRE产出至少 1 条诊断时会额外对该程序变异出最多 3 个“后代”继续跑——一个让输入保持在报出路径附近的反馈循环EXPLOIT_DESCENDANT_COUNT。每个用例可由其 seed 复现测试超时按max(60s, 迭代数 × 30ms)计算加大迭代数时超时会随之放宽。加大规模和固定种子结果可复现FUZZ_RULEno-array-index-as-key FUZZ_ITERATIONS200 FUZZ_SEED42 pnpm fuzz读懂运行结果通过条件测试通过意味着该规则在全部迭代中“survives fuzzing”——没有任何阻塞性发现。阻塞性发现有两类crash规则在访问一个可解析程序时抛出了异常slow单个文件耗时超过阈值默认 2000ms。注意慢判定有复核候选程序会被重新跑最多 2 次、取最快一次只有每次都超阈值才算发现目的是排除 CPU 争抢造成的墙钟尖峰。非阻塞advisory发现有两类默认只打印console.warn并落盘复现文件、不使测试失败invariant-violation语义保持的重写首尾注释、尾部未用声明、在顶层区块之间插入注释/空行改变了诊断签名说明规则依赖了偶然的源码形态verdict-dropverdict 保持型改写加括号、as-any 包裹、简洁箭头转块级等让已 FIRE 的规则完全不再报出。想开启不变量检查# 只告警 FUZZ_RULEno-array-index-as-key FUZZ_INVARIANTS1 pnpm fuzz # 告警并使其失败 FUZZ_RULEno-array-index-as-key FUZZ_STRICT1 pnpm fuzzFUZZ_STRICT1时所有发现含 advisory都会让测试失败。注意不变量类 oracle 只对 AST 规则生效scan 规则合法地匹配注释/字符串内容会被跳过。统计与覆盖加FUZZ_PRINT_STATS1会按下面这种格式输出该规则的统计文档示例具体数值随运行变化fuzz stats: no-array-index-as-key executed28 fired9 skipped-parse1 total41.2ms max3.5ms运行结束时还会打印 fire-coverage 汇总例如文档示例fuzz fire-coverage: 1/1 rules produced a diagnostic at least once这个数字而不是迭代次数才是框架本身的健康指标一条从不 FIRE 的规则只被 fuzz 到了它的早退分支。FUZZ_PRINT_SILENT1会列出从未 FIRE 的规则。复现文件任何发现都会把触发程序写到packages/fuzz/tmp/fuzz-findings/文件名形如ruleId-kind-seed-seed-序号.tsx文件头部带注释// rule:、// kind:、// seed: seed (iteration n)、// variant:如有、// detail:。拿这个文件即可回到确定性的复现路径。可选分支加入真实文件语料内置语料packages/fuzz/corpus含确认过的误报回归与 liveness 目标始终参与。若要叠加真实仓库文件用FUZZ_CORPUS_DIR指向一个克隆好的仓库目录例如仓库提供的固定 48 仓库样例语料sync-fuzz-corpus.ts# 需要已安装 bun会走网络 git 克隆产物在 packages/fuzz/tmp/corpus-repos/ bun packages/fuzz/scripts/sync-fuzz-corpus.ts这条命令的副作用先说清楚它会从固定 ref 做 blob-filter 克隆增量重跑可复用需要网络访问对已存在但 ref 不匹配的目录条目会先 fetch/checkout 重钉失败时删除后重新克隆。可选SYNC_LIMIT10前缀限制本次处理的仓库数量。然后对单条规则叠加语料跑FUZZ_CORPUS_DIRpackages/fuzz/tmp/corpus-repos FUZZ_RULEno-array-index-as-key pnpm fuzz语料加载有明确约束load-fuzz-corpus.ts只收.ts/.tsx/.js/.jsx含.txt后缀排除.d.ts跳过node_modules、.git、dist、build、coverage最多 400 个文件、单文件不超过 48KB、非空多个顶层仓库目录之间轮转取样保证每个仓库都有贡献。语料文件头可以写指令注释// rule: a, b关联规则、// file-path: path真实路径供路径门控规则识别、// verdict: pass确认的误报回归或// verdict: fail确认的真阳性。带 verdict 的种子会针对// rule:中点名的规则确定性地运行结果与声明不符会报verdict-mismatch。限制与排错FUZZ_ITERATIONS、FUZZ_SEED、FUZZ_SLOW_THRESHOLD_MS必须是正整数值非法时测试直接抛错而不是静默降为 0 轮0 轮会让整次运行变成假绿。slow的阈值默认 2000ms用FUZZ_SLOW_THRESHOLD_MS100可以捕获更低延迟的离群输入仍走“重跑取最快”的复核逻辑。源码中另有FUZZ_REQUIRE_FIRE1fuzz-rules.test.ts若该规则在整轮 fuzz 中一次诊断都没产出直接判失败——适合确认“分析路径确实被走到”的场合。框架只检查规则自身的健壮性与判定稳定性不评估规则检出率高低fire-coverage 为 0 时见上一条说明输入还没碰到报出路径。跑完一轮后若出现阻塞性发现按复现文件头部的seed和iteration用相同FUZZ_SEED重跑即可稳定复现把tmp/fuzz-findings/里的触发程序作为最小用例交给规则作者修复是 README 描述的完整闭环。【免费下载链接】react-doctorYour agent writes bad React. This catches it项目地址: https://gitcode.com/GitHub_Trending/re/react-doctor创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。