Skip to content
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

-Zmiri-tag-raw-pointers causes a simple copy_nonoverlapping to fail #2052

Closed
AaronKutch opened this issue Apr 6, 2022 · 3 comments
Closed
Labels
C-question Category: Not necessarily a bug, but someone asking for support

Comments

@AaronKutch
Copy link

I was trying out -Zmiri-strict-provenance on my library https://github.com/AaronKutch/awint and it lead to tests failing. I looked at the other things strict provenance turns on, and the problems start with -Zmiri-tag-raw-pointers. I think I have minimized it to:

fn main() {
    let mut x: [u64; 4] = [0, 1, 2, 3];
    unsafe {
        ptr::copy_nonoverlapping(x.as_ptr(), x.as_mut_ptr().add(2), 2);
    }
    assert_eq!(x, [0, 1, 0, 1]);
}

which fails with

error: Undefined Behavior: attempting a read access using <1670> at alloc776[0x0], but that tag does not exist in the borrow stack for this location
    --> C:\Users\aaron\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\intrinsics.rs:2103:14
     |
2103 |     unsafe { copy_nonoverlapping(src, dst, count) }
     |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |              |
     |              attempting a read access using <1670> at alloc776[0x0], but that tag does not exist in the borrow stack for this location
     |              this error occurs as part of an access at alloc776[0x0..0x10]
     |
     = help: this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental
     = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information

     = note: inside `std::intrinsics::copy_nonoverlapping::<u64>` at C:\Users\aaron\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\intrinsics.rs:2103:14
@RalfJung RalfJung added the C-question Category: Not necessarily a bug, but someone asking for support label Apr 6, 2022
@RalfJung
Copy link
Member

RalfJung commented Apr 6, 2022

Yeah, when you call x.as_mut_ptr() that creates a mutable reference to x and thus invalidates all previously created pointers, including the raw pointer that was returned by x.as_ptr(). So, this is expected.

See rust-lang/unsafe-code-guidelines#133 for the underlying issue. I am going to close the Miri side of this.

The fix is to not use any references when you do raw ptr shenanigans:

let mut x: [u64; 4] = [0, 1, 2, 3];
let ptr = x.as_mut_ptr();
// Reference-free zone begins here.
ptr::copy_nonoverlapping(ptr, ptr.add(2), 2);

@oli-obk

This comment was marked as resolved.

@AaronKutch
Copy link
Author

Ok, kind of makes sense

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-question Category: Not necessarily a bug, but someone asking for support
Projects
None yet
Development

No branches or pull requests

3 participants