The core implementation of the swap method in a matrix looks like this:
|
/// Swaps two elements using their linear index without bound-checking. |
|
#[inline] |
|
unsafe fn swap_unchecked_linear(&mut self, i1: usize, i2: usize) { |
|
let a = self.get_address_unchecked_linear_mut(i1); |
|
let b = self.get_address_unchecked_linear_mut(i2); |
|
|
|
mem::swap(&mut *a, &mut *b); |
|
} |
If
i1 and
i2 are equal, this method will cause mutable aliasing, which is undefined behavior under Rust's aliasing rules. However, the safe
swap methods don't check this:
|
/// Swaps two entries. |
|
#[inline] |
|
pub fn swap(&mut self, row_cols1: (usize, usize), row_cols2: (usize, usize)) { |
|
let (nrows, ncols) = self.shape(); |
|
assert!( |
|
row_cols1.0 < nrows && row_cols1.1 < ncols, |
|
"Matrix elements swap index out of bounds." |
|
); |
|
assert!( |
|
row_cols2.0 < nrows && row_cols2.1 < ncols, |
|
"Matrix elements swap index out of bounds." |
|
); |
|
unsafe { self.swap_unchecked(row_cols1, row_cols2) } |
|
} |
I believe that the best way to fix this would be to add more assertions to the safe method, and document these safety assumptions in the unsafe counterparts.
Edit: using ptr::swap instead of mem::swap fixes this.
The core implementation of the swap method in a matrix looks like this:
nalgebra/src/base/storage.rs
Lines 155 to 162 in 38add0b
If
i1andi2are equal, this method will cause mutable aliasing, which is undefined behavior under Rust's aliasing rules. However, the safeswapmethods don't check this:nalgebra/src/base/matrix.rs
Lines 1162 to 1175 in 38add0b
I believe that the best way to fix this would be to add more assertions to the safe method, and document these safety assumptions in the unsafe counterparts.Edit: using
ptr::swapinstead ofmem::swapfixes this.