Duplicate of#25860
Description
I tried this code:
fn static_str_identity()
-> for<'s> fn(&'s str) -> (
[&'static &'s (); 0],
&'static str,
)
{
|s: &str| (
[],
s,
)
}
fn main()
{
let f = static_str_identity();
let local = String::from("123");
let s: &'static str = f(&local).1; // <- should be rejected!
drop(local);
let _unrelated = String::from("UAF!");
dbg!(s); // <- compiles and prints `"UAF!"`
}
I expected to see this happen: argument requires that s
is borrowed for 'static
Instead, this happened: code compiles successfully and the excution potentially triggers Use-After-Free on the String local
.
rogram returned: 0
Program stderr
[/app/example.rs:21:5] s = "UAF!"
This seems very much like a Use-After-Free issue, and it's quite likely related to the compiler.It can be reproduced in the latest version of the Rust compiler.
- Demo: godbolt permalink
- Demo: on current playground
rustc --version --verbose
:
rustc 1.84.0-nightly (c1db4dc24 2024-10-25)
note: This issue appears to be different from #114936, which was related to the Fn*
Trait and was fixed in version 1.78; whereas this problem can still trigger a vulnerability in the latest version.
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
compiler-errors commentedon Oct 26, 2024
This is just another instance of #25860.
Subtyping when storing the return value of
static_str_identity()
causes us to "cast away" implied bounds of the output type of the function. This allows us to turn the signature from([&'static &'s (); 0], &'static str)
to([&'first &'s (); 0], &'second str)
, for two other arbitrary existential regions'first
and'second
, with only the requirement that'static: 'first
and'static: 'second
.Then later, when we check that the signature is well-formed at the call-site (
f(&local)
), we only require that's: 'first
due to the well-formedness of the[&'first &'s (); 0]
argument, but don't do anything for the'second
region. That allows us to later constrain'second: 'static
without actually "linking" it to's
, which is the lifetime of thelocal
string we're passing in.[-]&'s T` → &'static T` in safe code (UAF)[/-][+]`&'s T` → `&'static T` in safe code (UAF)[/+]apiraino commentedon Oct 30, 2024
For additional context, T-types is aware of this issue and the current status is summarized at this comment.
@rustbot label -I-prioritize
lcnr commentedon Jan 8, 2025
Closing in favor of #25860 which we're slowly working towards. Thank you for finding and reporting this issue 👍