跳到主要内容

你让 AI 找个 bug,它顺手把别名分析也实现了

摸鱼办主任
摸鱼办主任

· 阅读约 4 分钟

你有没有过这种时刻:让 AI 帮你改个变量名,它顺手把整个模块重构了,还附赠一份四百行的测试。

这事我吐槽过不止一次。这次来个更狠的——你让大模型从内核补丁里学找 bug,它把别名分析也一并实现了。

9 月 12 号 arXiv 上那篇 TyPatch,就是这么开场的。

它开炮的对象是之前那批工作:大模型读完历史补丁,直接吐出一个完整的静态分析检查器。

翻译成人话:你问它"这个补丁修的是什么毛病"。

它回你一个文件夹,里面装着对象追踪、别名分析、路径状态维护、过程间传播。

这个分工从第一天就透着不对劲。缺陷语义是什么?"这个指针用之前得先初始化"——一句话的事。分析器实现是什么?是怎么在几百万行穿插着函数指针和宏的 C 代码里,把这句话正确地跑出来——这是人家静态分析组干了二十年的事。两样打包成一个端到端的生成任务,约等于让新来的同事在填报销单的时候顺便把财务系统重写一遍。

论文自己那句说得比我狠:把语义还原和分析器实现耦合在单一的生成任务里,一条本来很简单的缺陷规则,就退化成了一个不稳定且昂贵的实现问题。

【灯光渐暗,一条三行就能写完的规则,在生成过程中逐渐长成了一棵树】

TyPatch 的方案朴素得有点没意思:拆开。

模型只干一件事,把补丁翻译成一条 typestate 规则。追踪谁、什么动作、什么守卫条件、状态怎么迁移、什么情况算违规。就这么多。执行全交给一个共享后端:动作绑定到程序事件、跨别名追踪对象身份、沿路径传播状态、统一出报告。

看出来了吧,前面那堆活一个没少——别名分析、路径状态、过程间传播全在。

变的只是它们的身份:从"每个补丁都得让模型现场发挥一遍",变成"后端写一次,所有规则共用"。

数字:Linux v6.16 上跑了 559 个缺陷,121 个被内核开发者确认;跟当下最先进的完整检查器构建流程做了 38 个补丁的配对,token 消耗降了 88.3% 到 90.1%,初始报告池的精确度是对方的 3.42 到 14.95 倍。

我最在意的不是 559。

是"省 token 的同时,精确度还涨了"。

这事挺反直觉的。过去两年我们对 prompt 的直觉一直是:上下文给得越全、要求写得越细、例子塞得越多,它写得越准。这里倒好,你让它少干点,它反而干对了。

我一开始以为是任务变小了所以便宜,后来才反应过来不是——是任务本身变干净了。还原语义是它擅长的;实现分析器是它不擅长、但特别自信的。你不让它碰后者,它就没机会"显灵"。

(这段写得有点像在讲道理,但确实是我看完的第一个念头。)

打住,说回数字。121/559 这个比例,有人会觉得不太好看。

恰恰相反。我觉得这是这篇论文最诚实的地方——写个检查器扫一遍大代码库,报出来的大部分是误报,这不叫失败,这叫工作流。真正该拉警报的是那种报了一堆、确认率高得不像话的工具,那你得怀疑它到底扫没扫。

(我也没跑过这 559 个,纯属对静态分析的朴素信仰。)

能拿出来到处用的,是那个分工,不是 559。

我们眼下对 AI 的默认用法基本是全包:写个功能,从需求理解、数据建模、接口设计一路到实现、测试、注释,一条龙。爽是真爽,出事的时候同样爽——因为你压根不知道是哪一环先烂的。

TyPatch 这个切法是:理解归理解,执行归执行,中间摆一个人能读、能审、能进版本库的东西当接口。

一条规则。

这个接口的价值不在优雅,在出事时你能定位。规则写错了改规则,后端有 bug 改后端,而不是对着一