forked from M-Labs/nalgebra
Fix panic in SparsityPattern::try_from_* if major index is out of bounds
This commit is contained in:
parent
e2c33b48ac
commit
e9b7718292
@ -606,6 +606,9 @@ fn pattern_format_error_to_csc_error(err: SparsityPatternFormatError) -> SparseF
|
|||||||
K::InvalidStructure,
|
K::InvalidStructure,
|
||||||
"Row indices are not monotonically increasing (sorted) within each column.",
|
"Row indices are not monotonically increasing (sorted) within each column.",
|
||||||
),
|
),
|
||||||
|
MajorIndexOutOfBounds => {
|
||||||
|
E::from_kind_and_msg(K::IndexOutOfBounds, "Column indices are out of bounds.")
|
||||||
|
}
|
||||||
MinorIndexOutOfBounds => {
|
MinorIndexOutOfBounds => {
|
||||||
E::from_kind_and_msg(K::IndexOutOfBounds, "Row indices are out of bounds.")
|
E::from_kind_and_msg(K::IndexOutOfBounds, "Row indices are out of bounds.")
|
||||||
}
|
}
|
||||||
|
@ -677,6 +677,9 @@ fn pattern_format_error_to_csr_error(err: SparsityPatternFormatError) -> SparseF
|
|||||||
K::InvalidStructure,
|
K::InvalidStructure,
|
||||||
"Column indices are not monotonically increasing (sorted) within each row.",
|
"Column indices are not monotonically increasing (sorted) within each row.",
|
||||||
),
|
),
|
||||||
|
MajorIndexOutOfBounds => {
|
||||||
|
E::from_kind_and_msg(K::IndexOutOfBounds, "Row indices are out of bounds.")
|
||||||
|
}
|
||||||
MinorIndexOutOfBounds => {
|
MinorIndexOutOfBounds => {
|
||||||
E::from_kind_and_msg(K::IndexOutOfBounds, "Column indices are out of bounds.")
|
E::from_kind_and_msg(K::IndexOutOfBounds, "Column indices are out of bounds.")
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,9 @@ impl SparsityPattern {
|
|||||||
return Err(NonmonotonicOffsets);
|
return Err(NonmonotonicOffsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
let minor_indices = &minor_indices[range_start..range_end];
|
let minor_indices = minor_indices
|
||||||
|
.get(range_start..range_end)
|
||||||
|
.ok_or(MajorIndexOutOfBounds)?;
|
||||||
|
|
||||||
// We test for in-bounds, uniqueness and monotonicity at the same time
|
// We test for in-bounds, uniqueness and monotonicity at the same time
|
||||||
// to ensure that we only visit each minor index once
|
// to ensure that we only visit each minor index once
|
||||||
@ -277,6 +279,8 @@ pub enum SparsityPatternFormatError {
|
|||||||
InvalidOffsetFirstLast,
|
InvalidOffsetFirstLast,
|
||||||
/// Indicates that the major offsets are not monotonically increasing.
|
/// Indicates that the major offsets are not monotonically increasing.
|
||||||
NonmonotonicOffsets,
|
NonmonotonicOffsets,
|
||||||
|
/// One or more major indices are out of bounds.
|
||||||
|
MajorIndexOutOfBounds,
|
||||||
/// One or more minor indices are out of bounds.
|
/// One or more minor indices are out of bounds.
|
||||||
MinorIndexOutOfBounds,
|
MinorIndexOutOfBounds,
|
||||||
/// One or more duplicate entries were detected.
|
/// One or more duplicate entries were detected.
|
||||||
@ -349,7 +353,7 @@ impl From<SparsityPatternFormatError> for SparseFormatError {
|
|||||||
| NonmonotonicMinorIndices => {
|
| NonmonotonicMinorIndices => {
|
||||||
SparseFormatError::from_kind_and_error(InvalidStructure, Box::from(err))
|
SparseFormatError::from_kind_and_error(InvalidStructure, Box::from(err))
|
||||||
}
|
}
|
||||||
MinorIndexOutOfBounds => {
|
MajorIndexOutOfBounds | MinorIndexOutOfBounds => {
|
||||||
SparseFormatError::from_kind_and_error(IndexOutOfBounds, Box::from(err))
|
SparseFormatError::from_kind_and_error(IndexOutOfBounds, Box::from(err))
|
||||||
}
|
}
|
||||||
PatternDuplicateEntry => SparseFormatError::from_kind_and_error(
|
PatternDuplicateEntry => SparseFormatError::from_kind_and_error(
|
||||||
@ -373,6 +377,9 @@ impl fmt::Display for SparsityPatternFormatError {
|
|||||||
SparsityPatternFormatError::NonmonotonicOffsets => {
|
SparsityPatternFormatError::NonmonotonicOffsets => {
|
||||||
write!(f, "Offsets are not monotonically increasing.")
|
write!(f, "Offsets are not monotonically increasing.")
|
||||||
}
|
}
|
||||||
|
SparsityPatternFormatError::MajorIndexOutOfBounds => {
|
||||||
|
write!(f, "A major index is out of bounds.")
|
||||||
|
}
|
||||||
SparsityPatternFormatError::MinorIndexOutOfBounds => {
|
SparsityPatternFormatError::MinorIndexOutOfBounds => {
|
||||||
write!(f, "A minor index is out of bounds.")
|
write!(f, "A minor index is out of bounds.")
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@ fn pattern_deserialize_invalid() {
|
|||||||
assert!(serde_json::from_str::<SparsityPattern>(r#"{"major_dim":3,"minor_dim":6,"major_offsets":[0, 2, 2, 5],"minor_indices":[0, 2, 3, 1, 4]}"#).is_err());
|
assert!(serde_json::from_str::<SparsityPattern>(r#"{"major_dim":3,"minor_dim":6,"major_offsets":[0, 2, 2, 5],"minor_indices":[0, 2, 3, 1, 4]}"#).is_err());
|
||||||
assert!(serde_json::from_str::<SparsityPattern>(r#"{"major_dim":3,"minor_dim":6,"major_offsets":[0, 2, 2, 5],"minor_indices":[0, 6, 1, 2, 3]}"#).is_err());
|
assert!(serde_json::from_str::<SparsityPattern>(r#"{"major_dim":3,"minor_dim":6,"major_offsets":[0, 2, 2, 5],"minor_indices":[0, 6, 1, 2, 3]}"#).is_err());
|
||||||
assert!(serde_json::from_str::<SparsityPattern>(r#"{"major_dim":3,"minor_dim":6,"major_offsets":[0, 2, 2, 5],"minor_indices":[0, 5, 2, 2, 3]}"#).is_err());
|
assert!(serde_json::from_str::<SparsityPattern>(r#"{"major_dim":3,"minor_dim":6,"major_offsets":[0, 2, 2, 5],"minor_indices":[0, 5, 2, 2, 3]}"#).is_err());
|
||||||
|
assert!(serde_json::from_str::<SparsityPattern>(r#"{"major_dim":3,"minor_dim":6,"major_offsets":[0, 10, 2, 5],"minor_indices":[0, 5, 1, 2, 3]}"#).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -148,8 +149,7 @@ fn csc_deserialize_invalid() {
|
|||||||
assert!(serde_json::from_str::<CscMatrix<i32>>(r#"{"nrows":6,"ncols":3,"col_offsets":[0,2,2,5],"row_indices":[0,5,1,2,3],"values":[0,1,2,3,4,5]}"#).is_err());
|
assert!(serde_json::from_str::<CscMatrix<i32>>(r#"{"nrows":6,"ncols":3,"col_offsets":[0,2,2,5],"row_indices":[0,5,1,2,3],"values":[0,1,2,3,4,5]}"#).is_err());
|
||||||
assert!(serde_json::from_str::<CscMatrix<i32>>(r#"{"nrows":6,"ncols":3,"col_offsets":[0,2,2,5],"row_indices":[0,5,1,8,3],"values":[0,1,2,3,4]}"#).is_err());
|
assert!(serde_json::from_str::<CscMatrix<i32>>(r#"{"nrows":6,"ncols":3,"col_offsets":[0,2,2,5],"row_indices":[0,5,1,8,3],"values":[0,1,2,3,4]}"#).is_err());
|
||||||
assert!(serde_json::from_str::<CscMatrix<i32>>(r#"{"nrows":6,"ncols":3,"col_offsets":[0,2,2,5],"row_indices":[0,5,1,2,3,1,1],"values":[0,1,2,3,4]}"#).is_err());
|
assert!(serde_json::from_str::<CscMatrix<i32>>(r#"{"nrows":6,"ncols":3,"col_offsets":[0,2,2,5],"row_indices":[0,5,1,2,3,1,1],"values":[0,1,2,3,4]}"#).is_err());
|
||||||
// The following actually panics ('range end index 10 out of range for slice of length 5', nalgebra-sparse\src\pattern.rs:156:38)
|
assert!(serde_json::from_str::<CscMatrix<i32>>(r#"{"nrows":6,"ncols":3,"col_offsets":[0,10,2,5],"row_indices":[0,5,1,2,3],"values":[0,1,2,3,4]}"#).is_err());
|
||||||
//assert!(serde_json::from_str::<CscMatrix<i32>>(r#"{"nrows":6,"ncols":3,"col_offsets":[0,10,2,5],"row_indices":[0,5,1,2,3],"values":[0,1,2,3,4]}"#).is_err());
|
|
||||||
assert!(serde_json::from_str::<CscMatrix<i32>>(r#"{"nrows":3,"ncols":6,"row_offsets":[0,2,2,5],"col_indices":[0,5,1,2,3],"values":[0,1,2,3,4]}"#).is_err());
|
assert!(serde_json::from_str::<CscMatrix<i32>>(r#"{"nrows":3,"ncols":6,"row_offsets":[0,2,2,5],"col_indices":[0,5,1,2,3],"values":[0,1,2,3,4]}"#).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,8 +188,7 @@ fn csr_deserialize_invalid() {
|
|||||||
assert!(serde_json::from_str::<CsrMatrix<i32>>(r#"{"nrows":3,"ncols":6,"row_offsets":[0,2,2,5],"col_indices":[0,5,1,2,3],"values":[0,1,2,3,4,5]}"#).is_err());
|
assert!(serde_json::from_str::<CsrMatrix<i32>>(r#"{"nrows":3,"ncols":6,"row_offsets":[0,2,2,5],"col_indices":[0,5,1,2,3],"values":[0,1,2,3,4,5]}"#).is_err());
|
||||||
assert!(serde_json::from_str::<CsrMatrix<i32>>(r#"{"nrows":3,"ncols":6,"row_offsets":[0,2,2,5],"col_indices":[0,5,1,8,3],"values":[0,1,2,3,4]}"#).is_err());
|
assert!(serde_json::from_str::<CsrMatrix<i32>>(r#"{"nrows":3,"ncols":6,"row_offsets":[0,2,2,5],"col_indices":[0,5,1,8,3],"values":[0,1,2,3,4]}"#).is_err());
|
||||||
assert!(serde_json::from_str::<CsrMatrix<i32>>(r#"{"nrows":3,"ncols":6,"row_offsets":[0,2,2,5],"col_indices":[0,5,1,2,3,1,1],"values":[0,1,2,3,4]}"#).is_err());
|
assert!(serde_json::from_str::<CsrMatrix<i32>>(r#"{"nrows":3,"ncols":6,"row_offsets":[0,2,2,5],"col_indices":[0,5,1,2,3,1,1],"values":[0,1,2,3,4]}"#).is_err());
|
||||||
// The following actually panics ('range end index 10 out of range for slice of length 5', nalgebra-sparse\src\pattern.rs:156:38)
|
assert!(serde_json::from_str::<CsrMatrix<i32>>(r#"{"nrows":3,"ncols":6,"row_offsets":[0,10,2,5],"col_indices":[0,5,1,2,3],"values":[0,1,2,3,4]}"#).is_err());
|
||||||
//assert!(serde_json::from_str::<CsrMatrix<i32>>(r#"{"nrows":3,"ncols":6,"row_offsets":[0,10,2,5],"col_indices":[0,5,1,2,3],"values":[0,1,2,3,4]}"#).is_err());
|
|
||||||
assert!(serde_json::from_str::<CsrMatrix<i32>>(r#"{"nrows":6,"ncols":3,"col_offsets":[0,2,2,5],"row_indices":[0,5,1,2,3],"values":[0,1,2,3,4]}"#).is_err());
|
assert!(serde_json::from_str::<CsrMatrix<i32>>(r#"{"nrows":6,"ncols":3,"col_offsets":[0,2,2,5],"row_indices":[0,5,1,2,3],"values":[0,1,2,3,4]}"#).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +133,17 @@ fn sparsity_pattern_try_from_invalid_data() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Major index out of bounds
|
||||||
|
let offsets = vec![0, 10, 2, 5];
|
||||||
|
let indices = vec![0, 1, 2, 3, 4];
|
||||||
|
let pattern = SparsityPattern::try_from_offsets_and_indices(3, 6, offsets, indices);
|
||||||
|
assert_eq!(
|
||||||
|
pattern,
|
||||||
|
Err(SparsityPatternFormatError::MajorIndexOutOfBounds)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// Minor index out of bounds
|
// Minor index out of bounds
|
||||||
let offsets = vec![0, 2, 2, 5];
|
let offsets = vec![0, 2, 2, 5];
|
||||||
|
Loading…
Reference in New Issue
Block a user