Skip to content

Undefined Behavior in some decomposition methods on SMatrix #1520

@JarredAllen

Description

@JarredAllen

I have some code that uses this library and was hitting undefined behavior as reported by Miri, and I was able to simplify it to this simple example that produces UB without any use of unsafe:

fn main() {
    let mut mat = nalgebra::SMatrix::<f32, 2, 2>::zeros_generic(nalgebra::Const, nalgebra::Const);
    mat[(0, 0)] = 1.0;
    mat[(1, 1)] = 1.0;
    println!("{:?}", mat.cholesky());
}

When run under cargo +nightly miri run, it reports this output:

error: Undefined Behavior: trying to retag from <2370> for Unique permission at alloc642[0xc], but that tag does not exist in the borrow stack for this location
   --> /home/jarred/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/raw.rs:192:9
    |
192 |         &mut *ptr::slice_from_raw_parts_mut(data, len)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |         |
    |         trying to retag from <2370> for Unique permission at alloc642[0xc], but that tag does not exist in the borrow stack for this location
    |         this error occurs as part of retag at alloc642[0xc..0x10]
    |
    = 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: <2370> was created by a SharedReadWrite retag at offsets [0x0..0x10]
   --> src/main.rs:5:22
    |
5   |     println!("{:?}", mat.cholesky());
    |                      ^^^^^^^^^^^^^^
help: <2370> was later invalidated at offsets [0x0..0x10] by a Unique retag
   --> src/main.rs:5:22
    |
5   |     println!("{:?}", mat.cholesky());
    |                      ^^^^^^^^^^^^^^
    = note: BACKTRACE (of the first span):
    = note: inside `std::slice::from_raw_parts_mut::<'_, f32>` at /home/jarred/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/raw.rs:192:9: 192:55
    = note: inside `<nalgebra::ViewStorageMut<'_, f32, nalgebra::Dyn, nalgebra::Const<1>, nalgebra::Const<1>, nalgebra::Const<2>> as nalgebra::RawStorageMut<f32, nalgebra::Dyn>>::as_mut_slice_unchecked` at /home/jarred/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nalgebra-0.33.2/src/base/matrix_view.rs:256:13: 256:56
    = note: inside `nalgebra::base::blas_uninit::axcpy_uninit::<nalgebra::uninit::Init, f32, nalgebra::Dyn, nalgebra::Dyn, nalgebra::ViewStorageMut<'_, f32, nalgebra::Dyn, nalgebra::Const<1>, nalgebra::Const<1>, nalgebra::Const<2>>, nalgebra::ViewStorage<'_, f32, nalgebra::Dyn, nalgebra::Const<1>, nalgebra::Const<1>, nalgebra::Const<2>>>` at /home/jarred/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nalgebra-0.33.2/src/base/blas_uninit.rs:105:13: 105:44
    = note: inside `nalgebra::base::blas::<impl nalgebra::Matrix<f32, nalgebra::Dyn, nalgebra::Const<1>, nalgebra::ViewStorageMut<'_, f32, nalgebra::Dyn, nalgebra::Const<1>, nalgebra::Const<1>, nalgebra::Const<2>>>>::axcpy::<nalgebra::Dyn, nalgebra::ViewStorage<'_, f32, nalgebra::Dyn, nalgebra::Const<1>, nalgebra::Const<1>, nalgebra::Const<2>>>` at /home/jarred/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nalgebra-0.33.2/src/base/blas.rs:300:18: 300:54
    = note: inside `nalgebra::base::blas::<impl nalgebra::Matrix<f32, nalgebra::Dyn, nalgebra::Const<1>, nalgebra::ViewStorageMut<'_, f32, nalgebra::Dyn, nalgebra::Const<1>, nalgebra::Const<1>, nalgebra::Const<2>>>>::axpy::<nalgebra::Dyn, nalgebra::ViewStorage<'_, f32, nalgebra::Dyn, nalgebra::Const<1>, nalgebra::Const<1>, nalgebra::Const<2>>>` at /home/jarred/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nalgebra-0.33.2/src/base/blas.rs:323:9: 323:38
    = note: inside `nalgebra::Cholesky::<f32, nalgebra::Const<2>>::new_internal` at /home/jarred/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nalgebra-0.33.2/src/linalg/cholesky.rs:233:17: 233:65
    = note: inside `nalgebra::Cholesky::<f32, nalgebra::Const<2>>::new` at /home/jarred/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nalgebra-0.33.2/src/linalg/cholesky.rs:196:9: 196:41
    = note: inside `nalgebra::linalg::decomposition::<impl nalgebra::Matrix<f32, nalgebra::Const<2>, nalgebra::Const<2>, nalgebra::ArrayStorage<f32, 2, 2>>>::cholesky` at /home/jarred/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nalgebra-0.33.2/src/linalg/decomposition.rs:260:9: 260:41
note: inside `main`
   --> src/main.rs:5:22
    |
5   |     println!("{:?}", mat.cholesky());
    |                      ^^^^^^^^^^^^^^

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

error: aborting due to 1 previous error

This seems to happen on the latest release to crates.io (0.33.2) as well as if I use the main branch of this repo. And cholesky() isn't the only method, hessenburg() also encounters UB according to Miri.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions