-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Safety of ptr::swap is unclear #81005
Comments
By the way, the second example of use std::ptr;
let mut array = [0, 1, 2, 3];
let x = array[0..].as_mut_ptr() as *mut [u32; 3]; // this is `array[0..3]`
// this as_mut_ptr() invalidates x!
let y = array[1..].as_mut_ptr() as *mut [u32; 3]; // this is `array[1..4]`
unsafe {
// using invalidated x
ptr::swap(x, y);
// (snip)
} |
cc @RalfJung |
The same argument seems to apply to Miri (tracking raw pointers) reported undefined behavior for the following code: unsafe {
let mut x: [i32; 3] = [100, 200, 300];
let p1: *mut i32 = x.as_mut_ptr();
let p2: *mut i32 = &mut *(p1.add(1)); // intermediate reference
std::ptr::copy(p1, p2, 2); // this is UB
} When I set the unsafe {
let mut x: [i32; 3] = [100, 200, 300];
let p1: *mut i32 = x.as_mut_ptr();
let p2: *mut i32 = &mut *p1; // intermediate reference
std::ptr::copy(p1, p2, 1); // miri treated this line as safe
} Note that the pointers are valid individually but not simultaneously in these examples. |
Well, they are valid individually, but they are not "both valid at the same time". In separation logic terms, we have #80778 is entirely unrelated, as it concerns the safety invariant of |
clarify safety documentation of ptr::swap and ptr::copy Closes rust-lang#81005
The
ptr::swap
function allows passed pointers to overlap, and its safety section is as follows:It says that both pointers must be "valid," but IIUC, the definition of validity becomes unclear under Stacked Borrows.
Consider the following program (all code in this comment is checked using Miri with
MIRIFLAGS="-Zmiri-track-raw-pointers"
):p1
andp2
are both "valid" at ☆ in the sense that this program is safe.p2
is invalidated when we perform a write usingp1
, but it's ok because we don't usep2
anymore.However, the following program exhibits UB in spite of the validity of
p1
andp2
, becauseptr::swap
first reads fromp1
and the read invalidatesp2
.Note that the intermediate unique reference (
&mut *
) is crucial for "separating" the two pointers.If we remove the intermediate reference, those pointers have the same capabilities.
In other words, the following program does not exhibit UB:
The difference between the two examples is so subtle that I'm not sure how to spell out the exact safety conditions for
ptr::swap
.This issue is found while formalizing the safety of
ptr::swap
in the Rustv project.The text was updated successfully, but these errors were encountered: