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

Stacked borrows miri failure in test_map_axis #1137

Closed
5225225 opened this issue Dec 19, 2021 · 1 comment · Fixed by #1138
Closed

Stacked borrows miri failure in test_map_axis #1137

5225225 opened this issue Dec 19, 2021 · 1 comment · Fixed by #1138
Labels

Comments

@5225225
Copy link

5225225 commented Dec 19, 2021

Running MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo miri test test_map_axis yields this stack trace

test test_map_axis ... error: Undefined Behavior: trying to reborrow for SharedReadOnly at alloc186627+0xc, but parent tag <502102> does not have an appropriate item in the borrow stack
    --> /home/jess/src/ndarray/src/iterators/mod.rs:225:63
     |
225  |         unsafe { self.inner.fold(init, move |acc, ptr| g(acc, &*ptr)) }
     |                                                               ^^^^^ trying to reborrow for SharedReadOnly at alloc186627+0xc, but parent tag <502102> does not have an appropriate item in the borrow stack
     |
     = 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 closure at /home/jess/src/ndarray/src/iterators/mod.rs:225:63
     = note: inside `<ndarray::iterators::Baseiter<i32, ndarray::Dim<[usize; 1]>> as std::iter::Iterator>::fold::<i32, [closure@<ndarray::iterators::ElementsBase<i32, ndarray::Dim<[usize; 1]>> as std::iter::Iterator>::fold<i32, [closure@ndarray::numeric::impl_numeric::<impl ndarray::ArrayBase<ndarray::ViewRepr<&i32>, ndarray::Dim<[usize; 1]>>>::sum::{closure#0}]>::{closure#0}]>` at /home/jess/src/ndarray/src/iterators/mod.rs:95:29
     = note: inside `<ndarray::iterators::ElementsBase<i32, ndarray::Dim<[usize; 1]>> as std::iter::Iterator>::fold::<i32, [closure@ndarray::numeric::impl_numeric::<impl ndarray::ArrayBase<ndarray::ViewRepr<&i32>, ndarray::Dim<[usize; 1]>>>::sum::{closure#0}]>` at /home/jess/src/ndarray/src/iterators/mod.rs:225:18
     = note: inside `<ndarray::iter::Iter<i32, ndarray::Dim<[usize; 1]>> as std::iter::Iterator>::fold::<i32, [closure@ndarray::numeric::impl_numeric::<impl ndarray::ArrayBase<ndarray::ViewRepr<&i32>, ndarray::Dim<[usize; 1]>>>::sum::{closure#0}]>` at /home/jess/src/ndarray/src/iterators/mod.rs:398:37
     = note: inside `ndarray::numeric::impl_numeric::<impl ndarray::ArrayBase<ndarray::ViewRepr<&i32>, ndarray::Dim<[usize; 1]>>>::sum` at /home/jess/src/ndarray/src/numeric/impl_numeric.rs:44:29
note: inside closure at tests/array.rs:2131:40
    --> tests/array.rs:2131:40
     |
2131 |     let b = a.map_axis(Axis(0), |view| view.sum());
     |                                        ^^^^^^^^^^
     = note: inside closure at /home/jess/src/ndarray/src/impl_methods.rs:2711:17
     = note: inside closure at /home/jess/src/ndarray/src/iterators/mod.rs:1495:29
     = note: inside `<std::slice::Iter<i32> as std::iter::Iterator>::fold::<(), [closure@ndarray::iterators::to_vec_mapped<std::slice::Iter<i32>, [closure@ndarray::impl_methods::<impl ndarray::ArrayBase<ndarray::OwnedRepr<i32>, ndarray::Dim<[usize; 2]>>>::map_axis<i32, [closure@tests/array.rs:2131:33: 2131:50]>::{closure#1}], i32>::{closure#0}]>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:2171:21
     = note: inside `ndarray::iterators::to_vec_mapped::<std::slice::Iter<i32>, [closure@ndarray::impl_methods::<impl ndarray::ArrayBase<ndarray::OwnedRepr<i32>, ndarray::Dim<[usize; 2]>>>::map_axis<i32, [closure@tests/array.rs:2131:33: 2131:50]>::{closure#1}], i32>` at /home/jess/src/ndarray/src/iterators/mod.rs:1494:5
     = note: inside `ndarray::impl_constructors::<impl ndarray::ArrayBase<ndarray::OwnedRepr<i32>, ndarray::Dim<[usize; 1]>>>::from_shape_trusted_iter_unchecked::<ndarray::StrideShape<ndarray::Dim<[usize; 1]>>, std::slice::Iter<i32>, [closure@ndarray::impl_methods::<impl ndarray::ArrayBase<ndarray::OwnedRepr<i32>, ndarray::Dim<[usize; 2]>>>::map_axis<i32, [closure@tests/array.rs:2131:33: 2131:50]>::{closure#1}]>` at /home/jess/src/ndarray/src/impl_constructors.rs:538:17
     = note: inside `ndarray::impl_methods::<impl ndarray::ArrayBase<ndarray::ViewRepr<&i32>, ndarray::Dim<[usize; 1]>>>::map::<i32, [closure@ndarray::impl_methods::<impl ndarray::ArrayBase<ndarray::OwnedRepr<i32>, ndarray::Dim<[usize; 2]>>>::map_axis<i32, [closure@tests/array.rs:2131:33: 2131:50]>::{closure#1}]>` at /home/jess/src/ndarray/src/impl_methods.rs:2476:17
     = note: inside `ndarray::impl_methods::<impl ndarray::ArrayBase<ndarray::OwnedRepr<i32>, ndarray::Dim<[usize; 2]>>>::map_axis::<i32, [closure@tests/array.rs:2131:33: 2131:50]>` at /home/jess/src/ndarray/src/impl_methods.rs:2710:13
note: inside `test_map_axis` at tests/array.rs:2131:13
    --> tests/array.rs:2131:13
     |
2131 |     let b = a.map_axis(Axis(0), |view| view.sum());
     |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside closure at tests/array.rs:2128:1
    --> tests/array.rs:2128:1
     |
2127 |   #[test]
     |   ------- in this procedural macro expansion
2128 | / fn test_map_axis() {
2129 | |     let a = arr2(&[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]);
2130 | |
2131 | |     let b = a.map_axis(Axis(0), |view| view.sum());
...    |
2157 | |     itertools::assert_equal(result.iter().cloned().sorted(), 1..=3 * 4);
2158 | | }
     | |_^
     = note: inside `<[closure@tests/array.rs:2128:1: 2158:2] as std::ops::FnOnce<()>>::call_once - shim` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
     = note: inside `<fn() as std::ops::FnOnce<()>>::call_once - shim(fn())` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
     = note: inside `test::__rust_begin_short_backtrace::<fn()>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:585:5
     = note: inside closure at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:576:30
     = note: inside `<[closure@test::run_test::{closure#2}] as std::ops::FnOnce<()>>::call_once - shim(vtable)` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
     = note: inside `<std::boxed::Box<dyn std::ops::FnOnce() + std::marker::Send> as std::ops::FnOnce<()>>::call_once` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:1811:9
     = note: inside `<std::panic::AssertUnwindSafe<std::boxed::Box<dyn std::ops::FnOnce() + std::marker::Send>> as std::ops::FnOnce<()>>::call_once` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:271:9
     = note: inside `std::panicking::r#try::do_call::<std::panic::AssertUnwindSafe<std::boxed::Box<dyn std::ops::FnOnce() + std::marker::Send>>, ()>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:406:40
     = note: inside `std::panicking::r#try::<(), std::panic::AssertUnwindSafe<std::boxed::Box<dyn std::ops::FnOnce() + std::marker::Send>>>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:370:19
     = note: inside `std::panic::catch_unwind::<std::panic::AssertUnwindSafe<std::boxed::Box<dyn std::ops::FnOnce() + std::marker::Send>>, ()>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:133:14
     = note: inside `test::run_test_in_process` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:608:18
     = note: inside closure at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:500:39
     = note: inside `test::run_test::run_test_inner` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:538:13
     = note: inside `test::run_test` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:572:28
     = note: inside `test::run_tests::<[closure@test::run_tests_console::{closure#2}]>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:313:17
     = note: inside `test::run_tests_console` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/console.rs:290:5
     = note: inside `test::test_main` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:124:15
     = note: inside `test::test_main_static` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:143:5
     = note: inside `main`
     = note: inside `<fn() as std::ops::FnOnce<()>>::call_once - shim(fn())` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
     = note: inside `std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys_common/backtrace.rs:123:18
     = note: inside closure at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:145:18
     = note: inside `std::ops::function::impls::<impl std::ops::FnOnce<()> for &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>::call_once` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:259:13
     = note: inside `std::panicking::r#try::do_call::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:406:40
     = note: inside `std::panicking::r#try::<i32, &dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:370:19
     = note: inside `std::panic::catch_unwind::<&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe, i32>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:133:14
     = note: inside closure at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:128:48
     = note: inside `std::panicking::r#try::do_call::<[closure@std::rt::lang_start_internal::{closure#2}], isize>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:406:40
     = note: inside `std::panicking::r#try::<isize, [closure@std::rt::lang_start_internal::{closure#2}]>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:370:19
     = note: inside `std::panic::catch_unwind::<[closure@std::rt::lang_start_internal::{closure#2}], isize>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:133:14
     = note: inside `std::rt::lang_start_internal` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:128:20
     = note: inside `std::rt::lang_start::<()>` at /home/jess/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:144:17
     = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
jturner314 added a commit to jturner314/ndarray that referenced this issue Dec 20, 2021
Before this commit, running `MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo
miri test test_map_axis` caused Miri to report undefined behavior in
the `test_map_axis` test. This commit fixes the underlying issue.
Basically, Miri doesn't like us using a reference to an element to
access other elements. Here's some sample code to illustrate the
issue:

```rust
let a: Vec<i32> = vec![5, 6];
let first_elt: &i32 = &a[0];
let ptr: *const i32 = first_elt as *const i32;
// Okay: the data is contained in the data referenced by `first_elt`.
let a0 = unsafe { &*ptr.offset(0) };
assert_eq!(*a0, 5);
// Not okay: the data is not contained in the data referenced by `first_elt`.
let a1 = unsafe { &*ptr.offset(1) };
assert_eq!(*a1, 6);
```

Before this commit, we were using `self.index_axis(axis,
0).map(|first_elt| ...)` to create views of the lanes, from references
to the first elements in the lanes. Accessing elements within those
views (other than the first element) led to the Miri error, since the
view's pointer was derived from a reference to a single element.

Thanks to @5225225 for reporting the issue. (This commit fixes rust-ndarray#1137.)
@jturner314
Copy link
Member

Thanks for reporting this. I've created #1138 to fix the issue.

@jturner314 jturner314 added the bug label Dec 20, 2021
bluss pushed a commit to jturner314/ndarray that referenced this issue Mar 9, 2024
Before this commit, running `MIRIFLAGS="-Zmiri-tag-raw-pointers" cargo
miri test test_map_axis` caused Miri to report undefined behavior in
the `test_map_axis` test. This commit fixes the underlying issue.
Basically, Miri doesn't like us using a reference to an element to
access other elements. Here's some sample code to illustrate the
issue:

```rust
let a: Vec<i32> = vec![5, 6];
let first_elt: &i32 = &a[0];
let ptr: *const i32 = first_elt as *const i32;
// Okay: the data is contained in the data referenced by `first_elt`.
let a0 = unsafe { &*ptr.offset(0) };
assert_eq!(*a0, 5);
// Not okay: the data is not contained in the data referenced by `first_elt`.
let a1 = unsafe { &*ptr.offset(1) };
assert_eq!(*a1, 6);
```

Before this commit, we were using `self.index_axis(axis,
0).map(|first_elt| ...)` to create views of the lanes, from references
to the first elements in the lanes. Accessing elements within those
views (other than the first element) led to the Miri error, since the
view's pointer was derived from a reference to a single element.

Thanks to @5225225 for reporting the issue. (This commit fixes rust-ndarray#1137.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants