| //@ 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. | |
| } |