From 306f096c64caf1a6ba6439311367c96c92934d42 Mon Sep 17 00:00:00 2001 From: Jack Wrenn Date: Tue, 9 Apr 2019 14:39:36 -0400 Subject: [PATCH] prevent constructing `MatrixSliceMutMN` for which disjoint indices may alias the same linear index Fixes #486. --- Cargo.toml | 1 + src/base/construction_slice.rs | 32 ++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 34 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 120d2916..4371df05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ generic-array = "0.12" rand = { version = "0.6", default-features = false } num-traits = { version = "0.2", default-features = false } num-complex = { version = "0.2", default-features = false } +num-rational = { version = "0.2", default-features = false } approx = { version = "0.3", default-features = false } alga = { version = "0.9", default-features = false } matrixmultiply = { version = "0.2", optional = true } diff --git a/src/base/construction_slice.rs b/src/base/construction_slice.rs index 0946653a..e5f311f8 100644 --- a/src/base/construction_slice.rs +++ b/src/base/construction_slice.rs @@ -2,6 +2,7 @@ use crate::base::dimension::{Dim, DimName, Dynamic, U1}; use crate::base::matrix_slice::{SliceStorage, SliceStorageMut}; use crate::base::{MatrixSliceMN, MatrixSliceMutMN, Scalar}; +use num_rational::Ratio; /* * * Slice constructors. @@ -107,6 +108,37 @@ impl<'a, N: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> "Matrix slice: input data buffer to small." ); + assert!({ + let nrows = nrows.value(); + let ncols = ncols.value(); + let rstride = rstride.value(); + let cstride = cstride.value(); + + // `Storage::linear_index` + let index = |i, j| (i * rstride) + (j * cstride); + + // The final condition of each arm is an expression in the form: + // index(i₀, j₀) != index(i₁, j₁) + // If this expression is `false`, then the values (i₀, j₀) + // and (i₁, j₁) are concrete examples of indices that would + // collide if the matrix was actually constructed. + nrows * ncols <= 1 || + match (rstride, cstride) { + (0, 0) => index(0, 0) != index(nrows - 1, ncols - 1), + (0, _) => nrows <= 1 || index(0, 0) != index(nrows - 1, 0), + (_, 0) => ncols <= 1 || index(0, 0) != index(0, ncols - 1), + (_, _) => { + let ratio = Ratio::new(rstride, cstride); + let numer = *ratio.numer(); + let denom = *ratio.denom(); + + nrows <= denom || ncols <= numer + || index(0, numer) != index(denom, 0) + } + } + }, + "Matrix slice: dimensions and strides result in aliased indices."); + unsafe { Self::from_slice_with_strides_generic_unchecked(data, 0, nrows, ncols, rstride, cstride) } diff --git a/src/lib.rs b/src/lib.rs index 1cab3da8..2c649f63 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,6 +112,7 @@ extern crate generic_array; extern crate matrixmultiply; extern crate num_complex; extern crate num_traits as num; +extern crate num_rational; extern crate rand; extern crate typenum;