-
-
Notifications
You must be signed in to change notification settings - Fork 14.4k
Open
Labels
A-NLLArea: Non-lexical lifetimes (NLL)Area: Non-lexical lifetimes (NLL)A-borrow-checkerArea: The borrow checkerArea: The borrow checkerA-closuresArea: Closures (`|…| { … }`)Area: Closures (`|…| { … }`)A-lifetimesArea: Lifetimes / regionsArea: Lifetimes / regionsC-bugCategory: This is a bug.Category: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-highHigh priorityHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.
Description
This unsoundness is an exploitation of the weirdness in #123312. See also #148854 for a similar unsoundness.
The below code causes a use-after-free (segfault in my testing).
type Payload = Box<i32>;
trait StaticToStatic {
fn static_to_static(self) -> &'static Payload where Self: 'static;
}
impl<'a> StaticToStatic for &'a Payload {
fn static_to_static(self) -> &'static Payload where Self: 'static {
self // Legal. 'a must be 'static due to Self: 'static
}
}
struct Wrap<T: StaticToStatic + 'static>(T);
trait ToStatic {
fn to_static(self) -> &'static Payload;
}
impl<T: StaticToStatic> ToStatic for Wrap<T> {
fn to_static(self) -> &'static Payload {
self.0.static_to_static() // Legal. T: 'static is implied by Wrap<T>
}
}
// Trait to allow mentioning FnOnce without mentioning the return type directly
trait MyFnOnce {
type MyOutput;
fn my_call_once(self) -> Self::MyOutput;
}
impl<F: FnOnce() -> T, T> MyFnOnce for F {
type MyOutput = T;
fn my_call_once(self) -> T {
self()
}
}
fn call<F: MyFnOnce<MyOutput: ToStatic>>(f: F) -> &'static Payload {
f.my_call_once().to_static()
}
fn extend<T: StaticToStatic>(x: T) -> &'static Payload {
let c = move || {
// Probably should be illegal, since Wrap requires T: 'static
Wrap(x)
};
call(c)
}
fn main() {
let x = Box::new(Box::new(1));
let y = extend(&*x);
drop(x);
println!("{y}"); // segfaults
}Meta
Reproducible on the playground with version 1.95.0-nightly (2026-01-24 f134bbc78dac04a17324)
Metadata
Metadata
Assignees
Labels
A-NLLArea: Non-lexical lifetimes (NLL)Area: Non-lexical lifetimes (NLL)A-borrow-checkerArea: The borrow checkerArea: The borrow checkerA-closuresArea: Closures (`|…| { … }`)Area: Closures (`|…| { … }`)A-lifetimesArea: Lifetimes / regionsArea: Lifetimes / regionsC-bugCategory: This is a bug.Category: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-highHigh priorityHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.
Type
Projects
Status
open/unblocked