40 lines
1.0 KiB
Rust
40 lines
1.0 KiB
Rust
//@ known-bug: #112905
|
|
//@ check-pass
|
|
|
|
// Classified as an issue with implied bounds:
|
|
// https://github.com/rust-lang/rust/issues/112905#issuecomment-1757847998
|
|
|
|
#![forbid(unsafe_code)] // No `unsafe!`
|
|
#![feature(type_alias_impl_trait)]
|
|
|
|
use std::any::Any;
|
|
|
|
/// Anything covariant will do, for this demo.
|
|
type T<'lt> = &'lt str;
|
|
|
|
type F<'a, 'b> = impl 'static + Fn(T<'a>) -> T<'b>;
|
|
|
|
fn helper<'a, 'b>(_: [&'b &'a (); 0]) -> F<'a, 'b> {
|
|
|x: T<'a>| -> T<'b> { x } // this should *not* be `: 'static`
|
|
}
|
|
|
|
fn exploit<'a, 'b>(a: T<'a>) -> T<'b> {
|
|
let f: F<'a, 'a> = helper([]);
|
|
let any = Box::new(f) as Box<dyn Any>;
|
|
|
|
let f: F<'a, 'static> = *any.downcast().unwrap_or_else(|_| unreachable!());
|
|
|
|
f(a)
|
|
}
|
|
|
|
fn main() {
|
|
let r: T<'static> = {
|
|
let local = String::from("...");
|
|
exploit(&local)
|
|
};
|
|
// Since `r` now dangles, we can easily make the use-after-free
|
|
// point to newly allocated memory!
|
|
let _unrelated = String::from("UAF");
|
|
dbg!(r); // may print `UAF`! Run with `miri` to see the UB.
|
|
}
|