Do raw pointer conversions erase pointer rights?
joshlf opened this issue · comments
The following passes Miri, but is it sound? In particular, I'm worried about the SharedReadWrite permission being "erased" at some point in the series of pointer casts.
fn main() {
let x = UnsafeCell::new(0);
let x = &x;
let x_ptr: *const UnsafeCell<usize> = x;
let x_ptr = x_ptr.cast::<usize>();
let x_ptr = x_ptr.cast_mut();
let x_ptr = NonNull::new(x_ptr).unwrap();
let x_ptr = x_ptr.as_ptr();
let x_ptr = x_ptr.cast_const();
let x_ptr = x_ptr.cast::<UnsafeCell<usize>>();
let _x = unsafe { &*x_ptr };
}
I'm pretty sure we can (and have to) promise that raw-pointer-to-raw-pointer operations such as cast or offset do not affect provenance, and hence this is sound.
The one aspect of this that is subtle (but that you're probably aware of) is that the initial cast from a reference to a raw pointer matters: x as *const _
and x as *mut _
are not equivalent if x
is a mutable reference. I view this as a bug in SB that is fixed by TB, but maybe for some reason we won't be able to fix this.
The one aspect of this that is subtle (but that you're probably aware of) is that the initial cast from a reference to a raw pointer matters:
x as *const _
andx as *mut _
are not equivalent ifx
is a mutable reference. I view this as a bug in SB that is fixed by TB, but maybe for some reason we won't be able to fix this.
Oh wow no, I had no idea. My mental model for the difference between *const
and *mut
has always been "they're exactly the same but it felt weird not to have two pointer types given that we have two reference types". That's reinforced by NonNull
not having different variants for const/mut, and all its methods only operating on/returning *mut
.
I think the question has been answered.