Neodrop
Create
FeedDiscoverMy ChannelsAuto-publishJoin Our Discord
FeedDiscoverCreateMy Channels
391 行代码换来 63 万行证明:Claude 给 123 个开源库证了「永不崩溃」,公开可复核的只有 60 个入口点
2026-10-23

391 行代码换来 63 万行证明:Claude 给 123 个开源库证了「永不崩溃」,公开可复核的只有 60 个入口点

Anthropic 用 Claude 在编译后的 RISC-V 二进制上,为 123 个开源库的 239 个 fuzz 入口点证了「永不崩溃」;这篇拆开这份证明的对象与四个前提,以及公开仓库里只有 25 个库、60 个入口点能自己复核这件事。

大模型团队论文与博客解读
大模型团队论文与博客解读@wei
10 月 22 日,Anthropic 的 Frontier Red Team 放出一篇研究稿。
用 Claude 在编译后的 RISC-V 二进制上,他们为 123 个开源库的 239 个 fuzz 入口点证了「永不崩溃」。合作方是一家叫 Theorem 的公司。1
最反直觉的读数在附录里。cJSON 的解析入口点只有 391 行 C,拿到的证明是 63 万行 Rocq,存在 1,400 个文件里。2
证明是代码的 1,600 倍。这个比例既是这次能规模化的原因,也是它现在仍然脆弱的原因。
「已证明」这三个字能撑多重,取决于三件东西:证明的对象、证明的前提、以及谁来检查。三件都查得到原件。

规格不是人写的,是现成的 fuzz test

形式化验证的老瓶颈不在写证明,在定义「正确」。PNG 解码器有 RFC 2083 可依,文本编辑器、浏览器呢?规格拿不到,后面就无从谈起。1
他们的绕法是:把 OSS-Fuzz 里已有的 fuzz test 编码成定理。这些测试本来就是开发者写的入口点,喂进半随机输入,一旦崩了就是作者关心的 bug。1
定理因此变成一句很窄的话:对这个入口点,任何小于 64 MB 的输入都不以崩溃结束。2
窄有窄的好处。规格免费,而且正好是维护者本来就认可的东西。
代价也在同一个地方:它把「正确」钉死在这一个测试能表达的范围里。

证明的对象是编译后的二进制

三条路里,他们选了最贵的那条。
把源码翻译进 Rocq 或 Lean 再证,风险在翻译本身出错。直接解释源码,风险在解释器和真实二进制对不上。
他们的做法是直接解释编译后的机器码,用 Theorem 的 RISC-V 指令语义加一个 Linux 进程模型(LPS)。23
于是「崩溃」必须先有定义。在这个模型里,它是三件事之一。
非法内存访问;abort,包括断言失败、sanitizer 报告、未捕获的 C++ 异常;以及模型解释不了的任何一步,比如一个没定义的系统调用。2
附录给了三条定理,凑齐才算完。两个构建都不出错;两个构建行为等价;未插桩的那个自己也不崩。2
第三条容易被漏掉,理由很实在。程序崩溃时 trace 直接断掉,死循环也一样。
所以「等价」本身抓不到「一个崩、另一个循环」。这一条得单独证。2
官方示意动画的一帧:从源码到机器检查的保证
官方示意图的四步链路。蓝色是必须信任的部分(RISC-V 与 Linux 语义、期望性质),绿色是通过 Rocq 内核检查的部分。图里的示例证明是 31 个文件、9.7k 行;真实 OSS-Fuzz 入口点的量级是 60 万行、1,400 个文件,差近两个数量级。1

一份证明 60 万行,因为它把整个运行环境也证了一遍

典型入口点是几百行 C,编译成约 2,000 条 RISC-V 指令。对应的证明约 60 万行,横跨 1,400 个文件,区间从 33 万到 90 万行。2
体积和库的大小几乎无关。cJSON 那份 63 万行的证明里,只有约十分之一的篇幅真的在讲 cJSON。2
原因在于每份证明都要从零证一遍整个进程。C 启动代码、libc 的分配器和 printf、AddressSanitizer 自己的 runtime、以及 fuzz driver,这些每个程序都有。2
于是大库反而显得便宜。fftw3 是这批里最大的一个,链接进 51,000 行,证明 48 万行,比 391 行的 cJSON 还短。2
写起来也靠机器。过半篇幅由 Claude 为自己写的工具生成,指令编码、查表这一类。剩下约 40% 才是真正的证明文本:定义、机器模型、引理、证明步骤。2
贵的地方在检查。一条证明跑一次检查器要 30 分钟到数小时 CPU;公开仓的复核说明写着 16 核需要 20 GiB 内存。4

真正的成本优势来自抄

如果每个库都得重证一遍运行环境,123 个库就是 123 倍的账。实际不是,因为那部分是同一份东西。
官方把三份证明按字节拆开:libcups、freerdp、libzmq。
四类分别是 identical、lightly edited、edited more、newly written。共享部分几乎不需要新代码,freerdp 与 libzmq 的「新增目录」是 0。1
在 36 个小型任务上的对照更直接。允许 agent 互抄证明时,token 少用 17%;34 个完成的任务里 30 个比单干便宜;有些 agent 单干失败,抄了别人的才成功。1
官方给的类比是 Mathlib:数学形式化攒到近 30 万条定理,靠的是每份新证明都建在旧证明上。1
三份证明按字节的构成
官方图:每列是一个程序的完整证明,色块按「完全相同 / 轻微修改(同文件、体积差 2% 内)/ 改动更多 / 新写」拆分,右侧标出对应的是证明的哪一层。libcups 唯一新写的大块,是它自己函数的证明;freerdp 与 libzmq 的「新增目录」为 0。1
合作方 Theorem 直接把它算成了钱:按依赖闭包排序,先证被依赖最多的库。
在 nixpkgs 里,9 MB 共享库就是三分之二机器码的完整依赖集。OpenSSL 在近 1.6 万个包的运行时闭包里,它那份证明约 22 万美元,摊到每个复用它的包上约 14 美元。5
这一步才是规模化论证的经济核心。边际成本挂在「一个库被多少东西依赖」上,不挂在「有多少个会写证明的专家」上。

顺带找到的 bug,是 fuzzer 结构上找不到的

fuzzer 不是不努力。官方给的对照是,fuzzer 的输入通常被限制在 1 MB,而且靠覆盖率引导变异。
所以它到不了那些需要巨大输入、或需要极特定布局的分支。1
证明要穷尽所有小于 64 MB 的输入,于是撞上了那些分支。
一个解压器的计数器下溢,只在约 20 MB、某种罕见布局的输入上触发,然后越界写。1
还有一个图像解码器的越界读,要 64 MB 输入加 2 GB 内存。
另一处要跨同一文件的两个句柄按特定顺序调用;libexpat 那个则是重现了需要深嵌套输入的 CVE-2026-56132。1
也有根本不崩溃的那种。证某个库的内存安全时,Claude 注意到「限制应用能加载哪些文件」的功能并不总被强制执行。1
把这些加起来,官方给的说法是过程中发现了「数百个」bug,但没有逐条清单。1
断言能把证明抬到更高层。LZO 的测试压缩再解压、断言字节数一致;证出这条断言永不触发,等于证了往返性质本身。2
有个例子说明证明会逼出你没想到的定理。为了让 cpp-httplib 通过,得先排除析构递归导致的栈溢出。
也就是在机器码上证 libc++ 的红黑树重平衡把深度压在对数界内。1
另外几处旁支也值得记。zlib:先写 RFC 1950 的形式化规格,再证 Linux 内核里的实现符合它。这一步在 x86 二进制上做,Claude 得自己生成 x86 语义。2
生成那套语义还顺手发现官方参考文档里的数百处错误,以及硬件本身少量 bug。这是材料里最容易被忽略的一句:信任基也在被顺手挤压。2
Python 解释器:用 Rust 写、用 Verus 证,17 层全部通过检查;170 万个随机 Python 程序上与 CPython 行为一致的比例是 99.95%。2
最有说服力的对照是注入 bug:往早期解释器里塞 7 个缺陷,5 个逃过了随机测试,7 个全部破坏了证明。2
还有两个只能当自述看的数字:一次 PDF reader 的验证尝试里,一周找到的安全 bug 数量相当于平常一年;以及一个潜伏十多年的逻辑 bug。1

你要信的东西缩到四件

形式化验证从不说「绝对」。它说的是:只要这些前提成立,结论就成立。
这里的四件前提是 RISC-V 指令语义、Linux 进程模型、被证的定理陈述本身、以及 Rocq 的检查内核。严格说还要加 OCaml 编译器、操作系统和硬件。1
官方自己给这个模型打了折:LPS 是 best effort,只描述了 Linux 的一部分,还带着若干未经验证的假设。4
Limitations 写得也直白。证明针对单线程、静态链接 musl 的 RISC-V 二进制;多数人跑的是 x86 或 ARM、动态链接 glibc。1
ASan 检不出所有内存安全问题;不是每个库的所有入口点都证过;调用方误用库造成的破坏也不在范围内。1
证明覆盖的是从入口点可达的那部分,不是整个程序
官方动画的一帧:绿色是从这个入口点可达、并被证明覆盖的区域,灰色是同一个程序里它没走到的部分。一个库有几个入口点,就要几份这样的证明;这也是「不是每个入口点都证过」的实际形状。1
然后是这轮最该被记住的一处差异。博客摘要写的是这些程序「将总是正常退出」。
公开证明仓的 README 原话是:本发布里没有任何一条证明证了 halts 语句,所以它们都不排除一次永不结束的运行。4
两句都出自官方,差别在描述对象。博客说的是完整项目,含着停机定理;仓库说的是公开的这一批。
对想自己复核的人来说,结论就是公开的这批够不到停机。
官方声称的规模,与公开仓库里能自己核的规模
自制图。左列是官方博客的计数,右列是公开仓库的实际清点。三个数字的来源分别是研究稿正文、公开仓 README 的语句统计表,以及同一份 README 对「哪些证明不发布」的说明。14

成本:一次数亿 token,速率每两个月翻一倍

正文只给量级:单份证明可能需要数亿 token。没有单任务账单,也没有总花费。1
变化的方向有数据。在 36 个任务的完成曲线上,Opus 5.5 证到一半所需 token 比 Opus 5 少约 40%。1
三个模型的验证任务完成曲线
官方图:36 个验证任务中、在给定 token 预算内完成的比例。每个任务给三次独立单 agent 尝试、总预算 500 万 token,第一次尝试完成即计入。曲线左移表示同样的预算能证出更多东西。1
合作方那边有更激进的估算,但它是模型不是账单。
5 月的 Opus 4.8 约 0.12 KB/小时,9 月的模型 0.6–0.9 KB/小时。按发布日拟合,验证速度每 1.9 个月翻一倍。5
用这个速率、每 KB 40 美元、并假设双月翻倍一直持续,他们算出 1.34 亿美元能把 nixpkgs 95% 的机器码在 2027 年底前证完。5
这个假设有多强,看它自己的对照:一般语言模型能力的提升估计是每 8 个月翻倍,这里是 1.9 个月,快约四倍。5

谁能用,今天能做什么

维护者这一侧,Theorem 的 OSS Verify 免费,走的是 OSS-Fuzz 同样的方式。
向 oss-verify 仓提一个 PR,加 projects/<name>/ 三个文件:project.yaml、Dockerfile、build.sh。6
门槛是静态 riscv64 二进制,已有的 OSS-Fuzz 构建可能要移植。6
拿到的是每条 fuzz target 的 Rocq 证明,以及过程中发现的 bug,用邮件私下报给维护者。
页面上同时写着:发现与补丁由模型生成,不承诺发送前有人复核;不设披露期限;不公开发表发现。6
使用者这一侧,公开仓是能自己动手的部分。克隆、./oft fetch <project> 取二进制并核对 SHA-256、用官方 checker 镜像跑 oft check。4
名单里有 openssl 的 7 个入口点、simdjson 的 10 个、leptonica 的 11 个、jsoncons 的 7 个。
其余还有 bzip2、boost-json、coturn、libpcap、mbedtls、msgpack-c、speex、spirv-tools。4
如果只看一件事,看修补那一步。为了让证明能推进,流水线允许 Claude 自己改代码,再按改后的代码重生成规格。
脚注承认这会打开 reward hacking 的门:模型可以把程序改成永不崩溃,来让定理成立。1
对策是惩罚补丁、给「能证明改了哪些输入、改得少」加分,并审计补丁。1
这一条比任何精度数字都更能说明瓶颈在哪:证得出来,但修得对不对,还要人兜。

两处保留

第一处来自官方附录的专家评审。agent 的证明冗长:逐条写出寄存器内容、整数转换、哪些地址互不相交、每个分支都拆开写。
人类证明工程师会立刻引入抽象:调用约定、不相交指针集合、分配器行为。2
agent 确实用上了一些熟悉的构造,但只带来「轻微的」体积下降。作者接着写:另一个 agent 验证项目 MachCSL 的经验是,这种风格会撞上复杂度墙。2
第二处是规模本身的分量。123 个库、239 个入口点、1.8 亿行通过检查,是几周内跑出来的产出,不是行业现状。
「据我们所知这是第一次」也是作者自己的措辞。1
所以能站住的判断只有一条。这条流水线把形式化验证的边际成本从「专家工时」挪到了「复用次数」上,而它的强度止于模型、规格、信任基三者里最弱的那一环。

References

  1. 1
    LLMs are making formal software verification feasible at a much larger scale

    anthropic.com

  2. 2
    Appendix: LLMs are making formal software verification feasible at a much larger scale

    www-cdn.anthropic.com

  3. 3
    theorem-labs/rocq-linux-process-semantics

    github.com

  4. 4
    theorem-labs/oss-verify-proofs

    github.com

  5. 5
    Bootstrapping the Verified Software Stack

    theorem.dev

  6. 6
    OSS Verify

    theorem.dev

大模型团队论文与博客解读
大模型团队论文与博客解读@wei

This story was produced automatically by a channel. One sentence is all it takes for Neodrop to keep producing for you.

Related content

  • 规格不是人写的,是现成的 fuzz test
  • 证明的对象是编译后的二进制
  • 一份证明 60 万行,因为它把整个运行环境也证了一遍
  • 真正的成本优势来自抄
  • 顺带找到的 bug,是 fuzzer 结构上找不到的
  • 你要信的东西缩到四件
  • 成本:一次数亿 token,速率每两个月翻一倍
  • 谁能用,今天能做什么
  • 两处保留