11 year old unsoundness bugs found in Rust borrow checker

11 year old unsoundness bugs found in Rust borrow checker

Given that this issue has been shared online and is currently getting quite a few visitors, here’s some additional context.

鉴于此问题已在网上分享并吸引了相当多的访问者,以下是一些补充背景信息。

Rust’s type system is intended to prevent memory unsafety. Upholding this promise is something we take very seriously, which is why we’ve been working on things like the next-generation trait solver, the region constraint rework, and more generally Project Zero. It is a large priority of the Types Team to fix all type system unsoundnesses and to work towards there being a solid foundation to minimize the risk of unknown ones.

Rust 的类型系统旨在防止内存不安全。我们非常认真地对待这一承诺,这也是我们致力于开发下一代特征求解器、区域约束重构以及更广泛的“零号项目”(Project Zero)的原因。修复所有类型系统的不健全之处并努力建立稳固的基础以最大限度地降低未知风险,是类型团队的首要任务。

This bug is a P-high issue and would have been P-critical regardless of whether people encountered it in the wild. The reason that it is “only P-high” is that it’s 11 years old. A bug like this which has not been found during the last 11 years cannot actually be that easy to hit.

此漏洞属于 P-high(高优先级)问题,无论人们是否在实际应用中遇到它,它本应被定为 P-critical(关键优先级)。它之所以“仅为 P-high”,是因为它已经存在 11 年了。像这样在过去 11 年中都未被发现的漏洞,实际上并不容易触发。

Looking at the bug itself, it is also very likely that this unsoundness has not caused memory unsafety by accident. While it looks easy to trigger, to exploit this you need an intentionally malicious Drop implementation.

从漏洞本身来看,这种不健全性极有可能并未意外导致内存不安全。虽然它看起来很容易触发,但要利用它,你需要一个蓄意恶意的 Drop 实现。

In the following code:

在以下代码中:

I expected to see this happen: program is not accepted

我预期会发生的情况:程序未被接受

Instead, this happened: program compiles and prints XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. With asan, the program will crash with a AddressSanitizer: stack-use-after-scope

实际发生的情况:程序编译通过并打印出 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。使用 asan 时,程序会因 AddressSanitizer: stack-use-after-scope 而崩溃。

Issue on current nightly, and stables at least down to 1.85.0

该问题存在于当前的 nightly 版本,以及至少回溯至 1.85.0 的稳定版本中。

Godbolt with asan: https://rust.godbolt.org/z/83MvfbKde Godbolt without asan: https://rust.godbolt.org/z/GsGdqqMWe

带有 asan 的 Godbolt 链接:https://rust.godbolt.org/z/83MvfbKde 不带 asan 的 Godbolt 链接:https://rust.godbolt.org/z/GsGdqqMWe

The core of the unsoundness:

该不健全性的核心:

My version of the code has been compiling ever since 1.18.0 (2017)

我的代码版本自 1.18.0 (2017) 以来一直都能编译通过。

How on earth was this not found before this???

这到底是怎么做到在此之前一直没被发现的???

Possibly related: #128225

可能相关:#128225

without relying on a static

不依赖于静态变量

Another version that segfaults/prints freed memory since 1.4

另一个自 1.4 版本起就会段错误/打印已释放内存的版本。

Another version, cuz why not. I think this version is probably the easiest to understand.

又一个版本,因为为什么不呢。我认为这个版本可能是最容易理解的。

I think unification just generally doesn’t check lifetime bounds of the type. Example with unifying coercion, without field assignment:

我认为统一化(unification)通常不会检查类型的生命周期边界。这是带有统一强制转换且没有字段赋值的示例:

fix: refuse handles in aggregate storage on both front ends

修复:在两个前端的聚合存储中拒绝句柄。

Hello everyone, mod here.

大家好,我是版主。

We’re preventively locking this issue to prevent spam and other unhelpful comments

我们正在预防性地锁定此问题,以防止垃圾信息和其他无益的评论。