Info
This post is auto-generated from RSS feed The Rust Programming Language Forum - Latest topics. Source: Is there a sound way to call `ptr::copy_nonoverlapping` with `count > 1` and `dst` being an element of `Vec>`?
Presuming I have a large (>= 64 KiB) v: Vec<UnsafeCell<u8>>
. I'd like to store multiple bytes in v
. v
already is zero initialized, so there is 2^16 or more 0u8
in it.
How would I call ptr::copy_nonoverlapping(src, dst, count)
(or its sibling ptr::copy_from_nonoverlapping
) such that there is no UB, with count
being (for the sake of an example) 16
, and with an offset of 3
into v
?
My naive (but according to stacked borrow checker in miri unsound) attempt was:
// init `v` with 64 KiB of null-bytes
let v_len = 0xffff;
let mut v: Vec<UnsafeCell<u8>> = Vec::with_capacity(v_len);
for _ in 0..v_len {
v.push(UnsafeCell::new(0));
}
// in the real code, `v` is only ever accessible as shared ref.
let v = &v;
// offset into `v` where we want to store `src`
let offset = 3;
// actual datum that we want to store in `v`
let src = [1u8; 16];
// do the thing, without UB pls
unsafe {
v.get_unchecked(offset)
.get()
.copy_from_nonoverlapping(src.as_ptr(), src.len())
}
Miri error message (click for more details)
I believe the issue to be, that miri correctly tracks that a given UnsafeCell<u8>
(which I get via Vec::get_unchecked
) only has pointer provenance to that single byte within v
, and not the 15 following ones. However, I know that, given that offset + src.len() < v.len()
there are enough further bytes after it for the copy_from_nonoverlapping
to be completely contained within the allocation of v
.
I understand that I can circumvent this by iterating over the UnsafeCell<u8>
in v
by hand, copying each byte individually (e.g. via ptr::copy_from_nonoverlapping
with count == 1
. Is there a better way?
Edit: in the non-minified context of the code I can only ever have a shared ref to v
, thus any solution requiring &mut v
unfortunately is off-limits. I did ask for the methods from ptr::*
combined with UnsafeCell
as they are fit for this purpose but forgot to explicitly name this constraint.
6 posts - 4 participants
🏷️ Rust_feed