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

miri:error printing the return value of align_to_mut #68549

Closed
rodrimati1992 opened this issue Jan 26, 2020 · 3 comments · Fixed by #69581
Closed

miri:error printing the return value of align_to_mut #68549

rodrimati1992 opened this issue Jan 26, 2020 · 3 comments · Fixed by #69581
Labels
A-miri Area: The miri tool C-bug Category: This is a bug. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@rodrimati1992
Copy link
Contributor

Attempting to run this code:

fn main() {
    dbg!(unsafe { [1u8,2,3,4,5].align_to_mut::<[u8;2]>() });
}

in miri 2020-01-15 in the playground,results in this error:


[src/main.rs:2] unsafe { [1u8, 2, 3, 4, 5].align_to_mut::<[u8; 2]>() } = (
    [],
error: Miri evaluation error: trying to reborrow for SharedReadOnly, but parent tag <1287> does not have an appropriate item in the borrow stack
    --> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1963:71
     |
1963 |             fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) }
     |                                                                       ^^^^^^^ trying to reborrow for SharedReadOnly, but parent tag <1287> does not have an appropriate item in the borrow stack
     |
     = note: inside call to `<&mut [[u8; 2]] as std::fmt::Debug>::fmt` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1959:81
     = note: inside call to `<&&mut [[u8; 2]] as std::fmt::Debug>::fmt` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/builders.rs:342:17
     = note: inside call to closure at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/result.rs:721:22
     = note: inside call to `std::result::Result::<(), std::fmt::Error>::and_then::<(), [closure@DefId(2:5728 ~ core[279e]::fmt[0]::builders[0]::{{impl}}[4]::field[0]::{{closure}}[0]) 0:&mut &mut std::fmt::DebugTuple, 1:&&dyn std::fmt::Debug]>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/builders.rs:334:23
     = note: inside call to `std::fmt::DebugTuple::field` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:2128:21
     = note: inside call to `<&(&mut [u8], &mut [[u8; 2]], &mut [u8]) as std::fmt::Debug>::fmt` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1097:5
     = note: inside call to `core::fmt::run` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/fmt/mod.rs:1061:17
     = note: inside call to `std::fmt::write` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/io/mod.rs:1426:15
     = note: inside call to `<std::io::StderrLock as std::io::Write>::write_fmt` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/io/stdio.rs:706:9
     = note: inside call to `<std::io::Stderr as std::io::Write>::write_fmt` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/io/stdio.rs:800:13
     = note: inside call to closure at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/thread/local.rs:262:16
     = note: inside call to `std::thread::LocalKey::<std::cell::RefCell<std::option::Option<std::boxed::Box<dyn std::io::Write + std::marker::Send>>>>::try_with::<[closure@DefId(1:2778 ~ std[8be3]::io[0]::stdio[0]::print_to[0]::{{closure}}[0]) 0:&std::fmt::Arguments, 1:&fn() -> std::io::Stderr], std::result::Result<(), std::io::Error>>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/io/stdio.rs:793:18
     = note: inside call to `std::io::stdio::print_to::<std::io::Stderr>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/io/stdio.rs:828:5
note: inside call to `std::io::_eprint` at <::std::macros::eprintln macros>:2:4
    --> src/main.rs:2:5
     |
2    |     dbg!(unsafe { [1u8,2,3,4,5].align_to_mut::<[u8;2]>() });
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     = note: inside call to `main` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:67:34
     = note: inside call to closure at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:52:73
     = note: inside call to closure at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/sys_common/backtrace.rs:129:5
     = note: inside call to `std::sys_common::backtrace::__rust_begin_short_backtrace::<[closure@DefId(1:6019 ~ std[8be3]::rt[0]::lang_start_internal[0]::{{closure}}[0]::{{closure}}[0]) 0:&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:52:13
     = note: inside call to closure at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/panicking.rs:305:40
     = note: inside call to `std::panicking::r#try::do_call::<[closure@DefId(1:6018 ~ std[8be3]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/panicking.rs:281:13
     = note: inside call to `std::panicking::r#try::<i32, [closure@DefId(1:6018 ~ std[8be3]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe]>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/panic.rs:394:14
     = note: inside call to `std::panic::catch_unwind::<[closure@DefId(1:6018 ~ std[8be3]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:51:25
     = note: inside call to `std::rt::lang_start_internal` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:67:5
     = note: inside call to `std::rt::lang_start::<()>`
     = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: aborting due to previous error

error: could not compile `playground`.

@jonas-schievink
Copy link
Contributor

Code of that function:

    pub unsafe fn align_to_mut<U>(&mut self) -> (&mut [T], &mut [U], &mut [T]) {
        // Note that most of this function will be constant-evaluated,
        if mem::size_of::<U>() == 0 || mem::size_of::<T>() == 0 {
            // handle ZSTs specially, which is – don't handle them at all.
            return (self, &mut [], &mut []);
        }

        // First, find at what point do we split between the first and 2nd slice. Easy with
        // ptr.align_offset.
        let ptr = self.as_ptr();
        let offset = crate::ptr::align_offset(ptr, mem::align_of::<U>());
        if offset > self.len() {
            (self, &mut [], &mut [])
        } else {
            let (left, rest) = self.split_at_mut(offset);
            // now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay
            let (us_len, ts_len) = rest.align_to_offsets::<U>();
            let mut_ptr = rest.as_mut_ptr();
            (
                left,
                from_raw_parts_mut(mut_ptr as *mut U, us_len),
                from_raw_parts_mut(mut_ptr.add(rest.len() - ts_len), ts_len),
            )
        }
    }

@jonas-schievink jonas-schievink added A-miri Area: The miri tool C-bug Category: This is a bug. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Jan 26, 2020
@nagisa
Copy link
Member

nagisa commented Jan 26, 2020

Somewhat simplified:

fn main() {
    unsafe {
        ([1u8,2,3,4,5].align_to_mut::<[u8;2]>().1)[0]
    };
}

Replacing [u8;2] with u16 makes miri shut up, even though the two types should be mostly equivalent.

If it is really a problem with how the align_to_mut function is implemented, the pointer cast in from_raw_parts_mut(mut_ptr as *mut U, us_len) is going to be it – though I believe I’ve done due diligence in making sure this code is valid for as long as transmuting T to U is valid.

cc @RalfJung

@RalfJung
Copy link
Member

This is where the tag gets removed from the borrow stack:

$ ./miri run-debug align.rs -Zmiri-track-pointer-tag=1287
note: popped tracked tag for item [Unique for <1287>]
    --> /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libcore/slice/mod.rs:2515:48
     |
2515 |                 from_raw_parts_mut(mut_ptr.add(rest.len() - ts_len), ts_len),
     |                                                ^^^^^^^^^^ popped tracked tag for item [Unique for <1287>]
     |
note: inside call to `core::slice::<impl [u8]>::align_to_mut::<[u8; 2]>` at align.rs:3:10
    --> align.rs:3:10
     |
3    |         ([1u8,2,3,4,5].align_to_mut::<[u8;2]>().1)[0]
     |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The problem is that rest.len() creates a new &[u8] that overlaps with the already created &mut [u8].

Replacing [u8;2] with u16 makes miri shut up, even though the two types should be mostly equivalent.

It also makes the middle slice empty, so there is no overlap.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-miri Area: The miri tool C-bug Category: This is a bug. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants