#Is this technically safe?

9 messages · Page 1 of 1 (latest)

tiny mango
#

Is this code technically safe?

#[derive(Default, Debug)]
struct Hello {
    a: u32,
    b: u32,
    c: u32,
}

fn do_something(h: &mut Hello) {
    // NEVER TOUCH h.a
    h.b = 10;
    h.c = 15;
}

fn main() {
    let mut h = Hello::default();
    let a = &mut h.a as *mut u32; // Normally this would be a borrowing err
    do_something(&mut h);
    unsafe {
        *a = 5;
    }
    
    println!("{:?}", h);
}

If I never touch h.a.

polar geyser
#

?miri

#[derive(Default, Debug)]
struct Hello {
    a: u32,
    b: u32,
    c: u32,
}

fn do_something(h: &mut Hello) {
    // NEVER TOUCH h.a
    h.b = 10;
    h.c = 15;
}

fn main() {
    let mut h = Hello::default();
    let a = &mut h.a as *mut u32; // Normally this would be a borrowing err
    do_something(&mut h);
    unsafe {
        *a = 5;
    }
    
    println!("{:?}", h);
}
carmine bladeBOT
#
error: Undefined Behavior: attempting a write access using <1666> at alloc852[0x0], but that tag does not exist in the borrow stack for this location
  --> src/main.rs:19:9
   |
19 |         *a = 5;
   |         ^^^^^^
   |         |
   |         attempting a write access using <1666> at alloc852[0x0], but that tag does not exist in the borrow stack for this location
   |         this error occurs as part of an access at alloc852[0x0..0x4]
   |
   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
   = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
help: <1666> was created by a SharedReadWrite retag at offsets [0x0..0x4]
  --> src/main.rs:16:13
   |
16 |     let a = &mut h.a as *mut u32; // Normally this would be a borrowing err
   |             ^^^^^^^^
help: <1666> was later invalidated at offsets [0x0..0xc] by a Unique retag
  --> src/main.rs:17:18
   |
17 |     do_something(&mut h);
   |                  ^^^^^^
   = note: BACKTRACE (of the first span):
   = note: inside `main` at src/main.rs:19:9: 19:15

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace```
tiny mango
#

oh okay thanks.

vapid marsh
#

Taking a &mut invalidates all previous derived pointers (at least under stacked borrows)

light cave
#

Notice the analysis doesn't actually care about the contents of do_something.

#

You passed a mutable reference so all bets are now off as to the state of the referent.

wet jungle
#

If you "swap" the safe-ness/raw-pointer-ness of do_something and a, then it can be sound ```rs
#[derive(Default, Debug)]
struct Hello {
a: u32,
b: u32,
c: u32,
}

unsafe fn do_something(h: *mut Hello) {
// NEVER TOUCH h.a
(*h).b = 10;
(*h).c = 15;
}

fn main() {
let mut h = Hello::default();
let h_ptr: *mut Hello = &mut h;
let a: &mut u32 = unsafe { &mut ((*h_ptr).a) };
unsafe { do_something(h_ptr) };
*a = 5;

println!("{:?}", h);

}