Rust soundness bug compiled since 2015, and its age is why it is rated high, not critical
A GitHub report shows safe Rust code reading freed memory through a struct's cleanup code. Variants compile back to Rust 1.4; the issue is still open.
OddBrief EditorialAI-assisted, human-reviewed
TechKey facts
- What
- lifetime bound bypassed via field assignment and Drop
- Since
- variants compile on Rust 1.4 (2015) and 1.18 (2017)
- Priority
- first P-critical, then P-high because of its age
- Status
- open as of October 14, no fix announced
A memory safety hole in the Rust compiler, reported on GitHub on October 13, lets ordinary-looking code read memory that has already been freed, and variants of it compile on Rust versions back to 1.4 from 2015. In a note on the issue, Rust contributor lcnr explained that the bug is rated P-high rather than P-critical precisely because it went unnoticed for 11 years.
What the bug does
Rust promises that code without the unsafe keyword cannot touch memory after it is gone. The compiler enforces this with lifetimes, which track how long each reference stays valid.
The report shows a way around that check. A struct can declare that its contents must live for the whole program. But if the struct starts empty and a reference to a short-lived local string is assigned to its field afterwards, the compiler accepts it. When the struct is dropped, its cleanup code treats that short-lived reference as permanent and can stash it somewhere global.
In the reporter's example, the program compiles and prints the text of a different string that later reused the same memory. With AddressSanitizer turned on, it crashes with a stack-use-after-scope error. The reporter confirmed the problem on current nightly builds and on stable releases at least back to 1.85.
Older than it first looked
Contributors quickly widened the picture. Within an hour, one showed that a simplified version compiles on Rust 1.18 from 2017 and asked how it had not been found before. Another posted a variant without any global variable that compiles on Rust 1.4, released in 2015. A third produced a version that segfaults or prints freed memory.
The issue is labeled as a soundness bug in the borrow checker, with tags for lifetimes, destructors and variance. Rust's triage bot first marked it P-critical, then P-high, after discussion on the project's chat.
Why it is not critical
A note added to the top of the issue sets out the reasoning. Its author says the bug would have been P-critical whether or not anyone had hit it, and is only P-high because of its age: "A bug like this which has not been found during the last 11 years cannot actually be that easy to hit."
The same note says the flaw is unlikely to have caused memory unsafety by accident. Exploiting it needs a deliberately malicious Drop implementation, the cleanup code that runs when a value goes out of scope.
The team points to longer projects meant to close this class of hole, including a next-generation trait solver and a rework of how lifetime constraints are handled. As of October 14 the issue was still open, and no fix had been announced in the thread.
Sources
- struct's lifetime requirements can be bypassed via covariant field assignmentrust-lang/rust on GitHubprimary source