taiki-e / atomic-memcpy

Byte-wise atomic memcpy.
https://docs.rs/atomic-memcpy
Apache License 2.0
28 stars 0 forks source link

MIRI friendly non-Copy object move? #13

Closed tower120 closed 2 hours ago

tower120 commented 2 hours ago

The following code does not pass MIRI run:

let v = UnsafeCell::new(String::from("hello"));   
let result = unsafe { atomic_memcpy::atomic_load(v.get(), Ordering::Relaxed) };
let s = unsafe { result.assume_init() };
mem::forget(v);  // Just in case, for MIRI's sake. 

I want to atomically transfer/move Drop-able object from v to s. Basically, I want MIRI-friendly ptr::read analog. Is that possible?

taiki-e commented 2 hours ago

Regardless of whether this crate or ptr::read is used, it must be properly expressed that the value may be invalidated using MaybeUninit.

taiki-e commented 2 hours ago

Well, in the example you showed you might actually just use ManuallyDrop instead of mem::forget. The important thing is not to drop the String contained in v after it has been copied by read, and not to make any claims about the validity of the values contained therein (access after read such as mem::forget in your code does that).

Either way, I suspect you will get a warning from Miri about ptr2int2ptr (as explained in the readme).

tower120 commented 1 hour ago

Oh I see now - "If the type being copied contains pointers it is not compatible with strict provenance because the copy does ptr-to-int transmutes." ManuallyDrop didn't helped... The error is:

error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 5 bytes of memory, but got 0x2359e[noalloc] which is a dangling pointer (it has no provenance)
   --> C:\Users\Andy\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:574:1
    |
574 | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 5 bytes of memory, but got 0x2359e[noalloc] which is a dangling pointer (it has no provenance)

So are these "ptr-to-int transmutes" are actual UB in Rust or are they just "incompatible" with MIRI?

taiki-e commented 1 hour ago

It is permissive-provenance compatible, strict-provenance incompatible.

It is not really difficult to make it strict compatible: https://github.com/taiki-e/atomic-memcpy/compare/HEAD...dev (aside from repr(packed) struct containing pointers)

tower120 commented 37 minutes ago

That would be nice! Would wrapping "repr(packed) struct containing pointers" in ptr-aligned struct solve that special case?

taiki-e commented 33 minutes ago

Would wrapping "repr(packed) struct containing pointers" in ptr-aligned struct solve that special case?

As for the ptr-aligned repr(packed) struct, it depends on where the pointer is eventually placed in the struct.