mccolljr / segvec

SegVec data structure for rust. Similar to Vec, but allocates memory in chunks of increasing size.
MIT License
35 stars 5 forks source link

miri stacked borrows error #29

Closed cehteh closed 1 year ago

cehteh commented 1 year ago

When running the tests with cargo +nightly miri test it errors out with

Undefined Behavior: attempting a read access using <441222> at alloc162558[0x10], but that tag does not exist in the borrow stack for this location

I think this is 'mostly' harmless as stacked borrows are overly restrictive. There are some ways to convince miri that it is correct, these may make the code a bit uglier, I may look into that soon. Eventually this should be fixed to be able to run the testsuite under miri anyways.

   --> src/lib.rs:522:13
    |
522 |             std::ptr::copy(src_ptr, dst_ptr, orig_len - seg_offset - 1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |             |
    |             attempting a read access using <441222> at alloc162558[0x10], but that tag does not exist in the borrow stack for this location
    |             this error occurs as part of an access at alloc162558[0x10..0x20]
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows 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
help: <441222> was created by a SharedReadWrite retag at offsets [0x0..0x10]
   --> src/lib.rs:520:27
    |
520 |             let dst_ptr = &mut self.segments[seg_idx][seg_offset] as *mut T;
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: BACKTRACE (of the first span):
    = note: inside `SegVec::<tests::DropCount<'_, i32>>::remove` at src/lib.rs:522:13: 522:72
note: inside `<Drain<'_, tests::DropCount<'_, i32>, mem_config::Exponential<1>> as std::iter::Iterator>::next`
   --> src/lib.rs:949:24
    |
949 |             let next = self.inner.remove(self.index);
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: inside `<&mut Drain<'_, tests::DropCount<'_, i32>, mem_config::Exponential<1>> as std::iter::Iterator>::next` at /home/ct/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:4010:9: 4010:24
    = note: inside `<&mut Drain<'_, tests::DropCount<'_, i32>, mem_config::Exponential<1>> as std::iter::Iterator>::fold::<(), [closure@std::iter::Iterator::for_each::call<tests::DropCount<'_, i32>, fn(tests::DropCount<'_, i32>) {std::mem::drop::<tests::DropCount<'_, i32>>}>::{closure#0}]>` at /home/ct/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:2480:29: 2480:40
    = note: inside `<&mut Drain<'_, tests::DropCount<'_, i32>, mem_config::Exponential<1>> as std::iter::Iterator>::for_each::<fn(tests::DropCount<'_, i32>) {std::mem::drop::<tests::DropCount<'_, i32>>}>` at /home/ct/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:856:9: 856:31
note: inside `<Drain<'_, tests::DropCount<'_, i32>, mem_config::Exponential<1>> as std::ops::Drop>::drop`
   --> src/lib.rs:981:9
    |
981 |         self.for_each(drop);
    |         ^^^^^^^^^^^^^^^^^^^
    = note: inside `std::ptr::drop_in_place::<Drain<'_, tests::DropCount<'_, i32>, mem_config::Exponential<1>>> - shim(Some(Drain<'_, tests::DropCount<'_, i32>, mem_config::Exponential<1>>))` at /home/ct/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:497:1: 497:56
    = note: inside `std::mem::drop::<Drain<'_, tests::DropCount<'_, i32>, mem_config::Exponential<1>>>` at /home/ct/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/mod.rs:987:24: 987:25
note: inside `tests::test_drain`
   --> src/tests.rs:274:5
    |
274 |     drop(d);
    |     ^^^^^^^
note: inside closure
   --> src/tests.rs:253:17
    |
252 | #[test]
    | ------- in this procedural macro expansion
253 | fn test_drain() {
    |                 ^
    = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to previous error
mccolljr commented 1 year ago

At some point this did run against miri, but that was 2 years ago and much has changed both within this crate and within miri since then. I can take a look at this soon-ish, as this crate is meant to be used in environments where you would absolutely expect miri to be happy with the code.