mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 06:22:00 +00:00
Auto merge of #127435 - GrigorenkoPV:tests-for-112905, r=cjgillot
Add tests for #112905 This is a part of #105107. Adds the tests from the OP in #112905.
This commit is contained in:
commit
25acbbd12f
53
tests/ui/implied-bounds/dyn-erasure-no-tait.rs
Normal file
53
tests/ui/implied-bounds/dyn-erasure-no-tait.rs
Normal file
@ -0,0 +1,53 @@
|
||||
//@ known-bug: #112905
|
||||
//@ check-pass
|
||||
|
||||
// Classified as an issue with implied bounds:
|
||||
// https://github.com/rust-lang/rust/issues/112905#issuecomment-1757847998
|
||||
|
||||
/// Note: this is sound! It's the "type witness" pattern (here, lt witness).
|
||||
mod some_lib {
|
||||
use super::T;
|
||||
|
||||
/// Invariant in `'a` and `'b` for soundness.
|
||||
pub struct LtEq<'a, 'b>(::std::marker::PhantomData<*mut Self>);
|
||||
|
||||
impl<'a, 'b> LtEq<'a, 'b> {
|
||||
pub fn new() -> LtEq<'a, 'a> {
|
||||
LtEq(<_>::default())
|
||||
}
|
||||
|
||||
pub fn eq(&self) -> impl 'static + Fn(T<'a>) -> T<'b> {
|
||||
|a| unsafe { ::std::mem::transmute::<T<'a>, T<'b>>(a) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use some_lib::LtEq;
|
||||
use std::{any::Any, cell::Cell};
|
||||
|
||||
/// Feel free to choose whatever you want, here.
|
||||
type T<'lt> = Cell<&'lt str>;
|
||||
|
||||
fn exploit<'a, 'b>(a: T<'a>) -> T<'b> {
|
||||
let f = LtEq::<'a, 'a>::new().eq();
|
||||
let any = Box::new(f) as Box<dyn Any>;
|
||||
|
||||
let new_f = None.map(LtEq::<'a, 'b>::eq);
|
||||
|
||||
fn downcast_a_to_type_of_new_f<F: 'static>(any: Box<dyn Any>, _: Option<F>) -> F {
|
||||
*any.downcast().unwrap_or_else(|_| unreachable!())
|
||||
}
|
||||
|
||||
let f = downcast_a_to_type_of_new_f(any, new_f);
|
||||
|
||||
f(a)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let r: T<'static> = {
|
||||
let local = String::from("…");
|
||||
let a: T<'_> = Cell::new(&local[..]);
|
||||
exploit(a)
|
||||
};
|
||||
dbg!(r.get());
|
||||
}
|
39
tests/ui/implied-bounds/dyn-erasure-tait.rs
Normal file
39
tests/ui/implied-bounds/dyn-erasure-tait.rs
Normal file
@ -0,0 +1,39 @@
|
||||
//@ 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.
|
||||
}
|
Loading…
Reference in New Issue
Block a user