I have to store a fat pointer obtained by Arc::into_raw in two separate struct fields. I'm building something similar to bytes, which has its focus on image buffers.
let raw = Arc::<[u8]>::from([0u8, 64u8, 128u8, 192u8]);
let len = raw.len();
let raw = Arc::into_raw(raw);
unsafe {
let ptr = { (&*raw).as_ptr() };
let data = std::slice::from_raw_parts(ptr, len);
// Arc::from_raw(data); // Miri errors if this lines is used instead of the last
Arc::from_raw(raw);
};
Miri shows the following error:
trying to retag from <359913> for SharedReadWrite permission at alloc135114[0x0], but that tag does not exist in the borrow stack for this location
| this error occurs as part of retag at alloc135114[0x0..0x18]
My workaround would be Boxing the obtained fat-pointer raw and thereby ad another level of indirection. Any Ideas how I can split raw into len and ptr and recombine them to reconstruct the Arc?
The pointer returned by Arc::into_raw and required by Arc::from_raw have write permissions too (that doesn't mean you can freely write through it though!). The pointer you're passing however has gone through a shared reference, which means it only has read permissions.
Don't get the pointer passed to Arc::from_raw from a reference. In your simple example above (&*raw).as_ptr() is the issue, change it to something like raw.cast::<u8>() instead.
Thank you very much! This put me in the right direction. There was another conversion into references, which i had to resolve. This is what I ended up with:
let raw = Arc::<[u8]>::from([0u8, 64u8, 128u8, 192u8]);
let len = raw.len();
let raw = Arc::into_raw(raw);
unsafe {
let ptr = raw.cast::<u8>();
let data = core::ptr::slice_from_raw_parts(ptr, len);
Arc::from_raw(data);
};