I came across this issue on the Rust issue tracker recently: https://github.com/rust-lang/rust/issues/57893.
One of the GitHub
comments
shows how you can abuse this bug to write a transmute
1 function without the
use of unsafe
(and then you can obviously use this to cause undefined
behavior in Safe Rust programs).
trait Object<U> {
type Output;
}
impl<T: ?Sized, U> Object<U> for T {
type Output = U;
}
fn transmute_obj<T: ?Sized, U>(x: <T as Object<U>>::Output) -> U {
x
}
fn transmute<T, U>(x: T) -> U {
transmute_obj::<dyn Object<U, Output = T>, U>(x)
}
fn main() {
// make a null pointer
let p = core::ptr::null_mut();
// "safely" transmute it into a reference
let x = transmute::<*mut i64, &'static i64>(p);
// access the reference
println!("x: {}", *x);
}
Pretty funny! It’s a compiler bug and will hopefully be fixed at some point (the issue has been open for 4 years though). I think it’s interesting to try to understand where the compiler is allowing something that it shouldn’t. This should work on all versions of Rust (at least up until 1.69 – the current version of Rust at the time of writing).
-
transmute
allows you to reinterpret a value of one type as a value of any other type without any checking (very unsafe). ↩︎