Home > Blockchain >  Rust: load values from raw pointers
Rust: load values from raw pointers

Time:09-17

I'm actually trying to understand how data are stored and loaded using pointers with rust, but when I run this code:

#[cfg(test)]
mod tests{
    fn get_pointer<T>(a:T) -> *const i32{
        ptr::addr_of!(a)
    }

    #[test]
    fn f(){
        unsafe {
            let a = 5;
            let pointer = get_pointer(a);
            let encoded = bincode::serialize(&(pointer as usize)).unwrap();
            let decoded = bincode::deserialize::<usize>(&encoded[..]).unwrap() as *const i32;
            let b = std::ptr::read(decoded);
            assert_eq!(a, b);
        }
    }
}

The value stored in b become 0 instead of 5, and I cannot figure out why this happens and how to solve this.

I think that the problem occurs because the value of a is dropped after the function returns the pointer but I'm not sure if that's right

CodePudding user response:

I think that the problem occurs because the value of a is dropped after the function returns the pointer but I'm not sure if that's right

Well yes, pretty much. The locals of a function only live for the extent of that function (which is why rustc will refuse compiling if you try to return a reference to function-local data), so get_pointer returns a dangling pointer, serializing and deserializing the pointer does quite literally nothing, and the ptr::read is UB:

Safety

Behavior is undefined if any of the following conditions are violated:

  • src must be valid for reads.
  • src must be properly aligned. Use read_unaligned if this is not the case.
  • src must point to a properly initialized value of type T.

Running the program using miri unambiguously flags the issue:

error: Undefined Behavior: pointer to alloc1416 was dereferenced after this allocation got freed
   --> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:703:9
    |
703 |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pointer to alloc1416 was dereferenced after this allocation got freed
    |
    = 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: inside `std::ptr::read::<i32>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:703:9
note: inside `main` at src/main.rs:12:17
   --> src/main.rs:12:17
    |
12  |         let b = ptr::read(decoded);
    |                 ^^^^^^^^^^^^^^^^^^

I'm actually trying to understand how data are stored and loaded using pointers with rust

Doing it that way is a terrible idea, you're stepping off way into UB land and that means all bets are off, what you observe (to the extent that you can observe anything) has no relations to defined semantics.

  • Related