Safe Rust prints freed stack memory
Rust issue #164250 exposes an 11-year borrow-checker unsoundness: covariant field assignment lets a malicious Drop read freed stack memory in safe Rust.
On October 13, 2026, someone filed rust-lang issue #164250 with a program the compiler accepts that assigns a reference to a local String into a struct field, lets the String go out of scope, and then prints its contents back out of freed stack memory. Under AddressSanitizer the same program crashes with stack-use-after-scope. There is no unsafe block anywhere in it, and it has compiled cleanly on stable Rust for years.
The setup is a generic struct with a 'static bound and a hand-written Drop:
struct Q<T: 'static + Send>(Option<T>);
impl<T: 'static + Send> Drop for Q<T> {
fn drop(&mut self) {
if let Some(t) = self.0.take() {
KEPT.lock().unwrap().push(Box::new(t));
}
}
}
The bound says T: 'static, so the Drop code is entitled to treat the stored value as living for the whole program. The hole is in how the field gets populated. Writing q.0 = Some(&l) assigns a reference to a local, which does not live for 'static. Because the field is covariant and unification does not check the type’s lifetime bounds on assignment, the compiler accepts the shorter-lived reference where a 'static one is required. When q is dropped at the end of its block, drop reads what it believes is a &'static String but is actually a dangling pointer to a local that already went out of scope. The reported example stashes that reference in a global Vec and reads it after the stack slot has been reused, which is why it prints a different string than the one that was stored.
The filer found several variants: one that reaches the same end state through unifying coercion with no field assignment at all, one phrased with a 'a: 'static bound that is probably the clearest to read, and plain versions that segfault or print freed memory. Their minimised reproductions compile on different versions going back a long way. One has built since 1.18.0 in 2017; another segfaults since 1.4. The issue reproduces on current nightly and on stables at least down to 1.85.0.
The Types Team marked it P-high and was explicit that it would have been P-critical regardless of whether anyone hit it in the wild. The reason it is only P-high, per @lcnr, is its age: a bug that has gone unfound for 11 years cannot be that easy to trigger. The same comment notes that exploiting it requires an intentionally malicious Drop implementation, and that it is very likely this has never caused memory unsafety by accident. The labels on the issue (A-variance, A-lifetimes, A-destructors, A-borrow-checker) point at the interaction between variance, region constraints, and destructor timing rather than at any one component.
For code you wrote and trust, this changes very little. You will not stumble into it writing ordinary Rust, and a decade of production code is the evidence. The part worth acting on is the trust boundary. The guarantee people lean on, that safe Rust cannot produce a use-after-free, now has a known exception, and the ingredient it needs is a hand-written Drop that quietly assumes a 'static lifetime it was never actually given. That is exactly the kind of thing that can sit in a dependency or a proc-macro you did not audit. If you run untrusted or security-sensitive Rust, a malicious destructor is a concrete vector against the memory-safety assumption, not a theoretical one.
The practical move is to run those builds under AddressSanitizer in CI. The reproductions fault as stack-use-after-scope, which ASan catches cleanly, so it will flag an exploit attempt that passes type-checking. There is no stable release to fall back to, since the bug reproduces straight through current stables; the fix is being tracked under the Types Team’s region constraint rework and the broader Project Zero effort to close type-system unsoundnesses. Until that lands, the compiler’s acceptance of a 'static-bounded Drop is not by itself proof that the stored reference actually lives that long.
Keep Reading
AhsayCBSAhsay's August patch left the RCE flaws exploitable
Ahsay's August AhsayCBS patches failed to close two exploited flaws; new hotfixes v10.3.4.45 and v9.15.2.70 fix the web shell and miner chain.
AI securityAI labs skipped decades-old containment, models escaped
Cybersecurity experts say the recent 'rogue AI' incidents came from misconfigured sandboxes and absent monitoring, not clever models.
ai-securityFour frontier labs each had a model break containment
Experts say recent 'rogue AI' incidents were containment failures at frontier labs, not emergent intelligence, and what CISOs should do about it.
Latest on the Wire
Full wire →- 95 Arrested in Global CSAM CrackdownBleepingComputer
- AhsayCBS Releases Fixes for Exploited Web Shell, Crypto-Miner FlawsThe Hacker News
- AI Builds Spot-the-Difference Tree Game in 3 HoursSimon Willison
- AI Gauges Cryptanalysis Effort on Public-Key AlgorithmsSchneier on Security
New signal daily · RSS
Stay in the loop
New writing delivered when it's ready. No schedule, no spam.