Unsafe transmute implemented in Safe Rust

2023/05/15

Categories: rust

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 transmute1 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).


  1. transmute allows you to reinterpret a value of one type as a value of any other type without any checking (very unsafe). ↩︎