Skip to content

Commit

Permalink
Fix Index conversion turning OOB
Browse files Browse the repository at this point in the history
  • Loading branch information
mulimoen committed Jan 20, 2025
1 parent cabaedb commit bec1c5b
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
8 changes: 7 additions & 1 deletion sprs/src/sparse/csmat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1788,6 +1788,11 @@ pub mod raw {

assert!(indptr.iter().all(num_traits::Zero::is_zero));

assert!(
I::try_from_usize(mat.rows()).is_some(),
"Index type is not large enough to hold the number of rows requested (I::max_value={:?} vs. required {})", I::max_value(), mat.rows(),
);

for vec in mat.outer_iterator() {
for (inner_dim, _) in vec.iter() {
indptr[inner_dim] += Iptr::one();
Expand All @@ -1805,10 +1810,11 @@ pub mod raw {
}

for (outer_dim, vec) in mat.outer_iterator().enumerate() {
let outer_dim = I::from_usize_unchecked(outer_dim);
for (inner_dim, val) in vec.iter() {
let dest = indptr[inner_dim].index();
data[dest] = val.clone();
indices[dest] = I::from_usize_unchecked(outer_dim);
indices[dest] = outer_dim;
indptr[inner_dim] += Iptr::one();
}
}
Expand Down
33 changes: 33 additions & 0 deletions sprs/tests/gh374.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use ndarray::Array2;
use sprs::CsMatI;

type Mat = CsMatI<f32, u16, usize>;

fn dense_nnz(arr: &Array2<f32>) -> usize {
arr.iter().map(|&f| usize::from(f != 0.0)).sum()
}

#[test]
#[should_panic(expected = "Index type is not large enough to hold")]
fn main() {
// create matrix so that row index doesn't fit into column index type after transposition
let mut x_sprs = Mat::zero((1_usize << 18, usize::from(1_u16 << 4)));
x_sprs.insert(1_usize << 17, usize::from(1_u16 << 2), 1.0);

// compute X^T * X in the sparse representation
let x_t_sprs = x_sprs.transpose_view();
let x_t_x_sprs = &x_t_sprs * &x_sprs;

// compute X^T * X in the dense representation
let x_dense = x_sprs.to_dense();
let x_t_x_dense = x_dense.t().dot(&x_dense);

// convert sparse result to dense representation for comparison
let x_t_x_sprs_to_dense = x_t_x_sprs.to_dense();

assert_eq!(x_sprs.nnz(), 1);
assert_eq!(x_t_x_sprs.nnz(), 1);
assert_eq!(dense_nnz(&x_dense), 1);
assert_eq!(dense_nnz(&x_t_x_dense), 1);
assert_eq!(dense_nnz(&x_t_x_sprs_to_dense), 1);
}

0 comments on commit bec1c5b

Please sign in to comment.