在 Rust 借用检查器中发现的 11 年陈旧不健全性漏洞
Rust 的借用检查器中发现了一个已有 11 年之久的健全性漏洞:涉及生命周期和自定义 `Drop` 实现的看似普通代码会被错误接受,从而允许引用活得比它所指向的数据更久。评论者分析了这如何违反 Rust 对内存安全的核心承诺,强调这属于编译器实现错误而非语言类型系统本身的缺陷,并指出它似乎需要一个刻意构造的析构函数才能转化为实际利用。此事也引发了更广泛的争论:与 C 相比 Rust 到底有多“安全”、任何类型系统或形式化证明的边界在哪里,以及包括 AI 在内的工具在发现此类细微编译器 bug 方面扮演何种角色。
漏洞性质
- 借用检查器中围绕
T: 'static和Drop的不健全性。 - 最小示例:一个带有
Q<T: 'static>(Option<T>)的泛型结构体,以及同样受'static约束的Drop实现。 - 编译器错误地允许在
Q中存储非'static引用(例如带有栈生命周期的&l),而Q本应只包含'static数据。 - 然后析构函数可能把它当作
'static来处理,例如将其藏进全局变量中,从而导致 use-after-free。
为什么一直没有被发现
- 触发模式被认为不寻常:需要一个自定义
Drop,并且生命周期约束以特定方式组合。 - 对“正常”自定义
Drop的普遍程度存在争论:有人说很少见,也有人说很常见,尤其是在 FFI 场景中;但这种精确模式很少见。 - 许多无效的生命周期程序可能不会显式崩溃,因此即使漏洞被触发,也未必会出现明显故障。
安全保证、不健全性与 UB
- 说明:
- 不健全性 = 安全 Rust 由于编译器/类型检查器缺陷而导致 UB。
- 规范中的 UB = 用户越出了明确定义的行为范围。
- 这个漏洞在编译器中,而不在 Rust 预期的生命周期规则中;修复方法是拒绝这类代码。
- 有人指出仍有许多未解决的不健全性问题;也有人强调修复可以在补丁版本中发布,而受影响的代码从未是“有效的 Rust”。
与 C 和其他语言的比较
- 有人借此认为 Rust 的安全宣传被夸大了,或者会给人一种虚假的安全感。
- 也有人反驳说,C/C++ 既有编译器 bug,又有普遍存在的语言级 UB,因此 Rust 仍然是安全性上的重大进步。
- 讨论还指出,没有任何语言能做到绝对安全;目标是让某些 bug 类别变得不可能,或极其罕见。
形式化方法与 AI
- 提到了当前对 Rust 或其子集进行形式化规范/证明的持续努力。
- 也承认即使是证明助手、规范和底层数学本身也可能出错,因此不可能有绝对保证。
- 有人认为 AI/LLM 是通过 fuzzing/搜索编译器来发现此类漏洞的有前景工具;也有人对此持怀疑或对 AI 炒作感到疲惫。
社区与社会动态
- 有人抱怨 Rust 传教式推广,以及对其他语言的贬低;也有人为官方表述更为克制而辩护。
- 关于对单个漏洞的过度反应也有元讨论:有人呼吁保持视角——这是真实但狭窄的缺陷,而不是 Rust 模型整体失败。