Returning static reference by casting to raw pointer and back to reference

I found some code similar to the one below.
I wanted to ask if it is undefined behaviour to return this &'static u8 reference fromfoo since the x from which the return value is constructed clearly doesn't live long enough.

fn main() {
    let a;
    {
        let x: u16 = 256;
        a = foo((&x as *const _) as usize);
    }

    dbg!(a);
}

fn foo(x: usize) -> &'static u8 {
    unsafe {&*(x as *const _)}
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.86s
     Running `target/debug/playground`
[src/main.rs:8] a = 0

You can run Miri on your playground via Tools > Miri. Miri will tell you it's undefined behavior.

1 Like

If you run the program via Tools>Miri, you'll see

Miri Output
warning: integer-to-pointer cast
  --> src/main.rs:12:15
   |
12 |     unsafe {&*(x as *const _)}
   |               ^^^^^^^^^^^^^^^ integer-to-pointer cast
   |
   = help: This program is using integer-to-pointer casts or (equivalently) `ptr::from_exposed_addr`,
   = help: which means that Miri might miss pointer bugs in this program.
   = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.from_exposed_addr.html for more details on that operation.
   = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead.
   = help: You can then pass the `-Zmiri-strict-provenance` flag to Miri, to ensure you are not relying on `from_exposed_addr` semantics.
   = help: Alternatively, the `-Zmiri-permissive-provenance` flag disables this warning.
   = note: BACKTRACE:
   = note: inside `foo` at src/main.rs:12:15: 12:30
note: inside `main`
  --> src/main.rs:5:13
   |
5  |         a = foo((&x as *const _) as usize);
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: Undefined Behavior: constructing invalid value: encountered a dangling reference (use-after-free)
 --> src/main.rs:8:5
  |
8 |     dbg!(a);
  |     ^^^^^^^ constructing invalid value: encountered a dangling reference (use-after-free)
  |
  = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
  = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
  = note: BACKTRACE:
  = note: inside `main` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/macros.rs:352:13: 352:16
  = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)

Miri is a sanitizing interpreter capable of catching most forms of UB in Rust.

This program exhibits UB, because it dereferences a dangling pointer. The lifetime extension to &'static itself is not UB, merely unsound, meaning that it makes it possible for safe code to cause UB in the future.

A soundness issue in a safe API is typically considered just as bad as actual UB. The fix is to mark the function as unsafe and document its soundness conditions: in this case, that the created reference is not used in violation of its source lifetime.

1 Like

Thanks a lot for your answers :slight_smile: