Skip to content

Miri reports stacked borrowing error in unsafe cast from element to array #24

Closed
@brson

Description

@brson

While testing tikv with miri I came across a report about a stacked borrowing violation in ryu, which we use via serde_json.

The error can be triggered against commit 90e4688 with miri from nightly-2020-04-17 by running:

cargo +nightly-2020-04-17 miri test

which outputs the error

running 12 tests
error: Undefined Behavior: no item granting write access to tag <untagged> found in borrow stack.
    --> /home/ubuntu/.rustup/toolchains/nightly-2020-04-17-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore/intrinsics.rs:2001:5
     |
2001 |     copy_nonoverlapping(src, dst, count)
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item granting write access to tag <untagged> found in borrow stack.
     |
     = help: this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimenta
l
     = 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::<u8>` at /home/ubuntu/.rustup/toolchains/nightly-2020-04-17-x86_64-unknown-linux-gn
u/lib/rustlib/src/rust/src/libcore/intrinsics.rs:2001:5
     = note: inside `ryu::raw::format64` at /home/ubuntu/ryu/src/pretty/mod.rs:69:9
     = note: inside `<f64 as ryu::buffer::Sealed>::write_to_ryu_buffer` at /home/ubuntu/ryu/src/buffer/mod.rs:197:9
     = note: inside `ryu::Buffer::format_finite::<f64>` at /home/ubuntu/ryu/src/buffer/mod.rs:88:21
     = note: inside `ryu::Buffer::format::<f64>` at /home/ubuntu/ryu/src/buffer/mod.rs:65:13

The cause seems to be this code:

     #[inline]
     #[cfg(maybe_uninit)]
     fn first_byte_pointer_mut(&mut self) -> *mut u8 {
        self.bytes[0].as_mut_ptr()
     }

which takes a pointer to the first element of an array, then later treats it as a pointer to an array.

I am not sure whether this is truly UB, but this diff silences miri:

     #[inline]
     #[cfg(maybe_uninit)]
     fn first_byte_pointer_mut(&mut self) -> *mut u8 {
-        self.bytes[0].as_mut_ptr()
+        self.bytes.as_mut_ptr() as *mut u8
     }

Unfortunately, after the patch miri fails to terminate.

I am unsure if this is a bug or not. cc @RalfJung

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions