VYPR
Medium severity6.2GHSA Advisory· Published May 8, 2026· Updated May 13, 2026

CVE-2026-42199

CVE-2026-42199

Description

Grid is a data structure grid for rust. From version 0.17.0 to before version 1.0.1, an integer overflow in Grid::expand_rows() can corrupt the relationship between the grid’s logical dimensions and its backing storage. After the internal invariant is broken, the safe API get() may invoke get_unchecked() with an invalid index, resulting in Undefined Behavior. This issue has been patched in version 1.0.1.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
gridcrates.io
>= 0.17.0, < 1.0.11.0.1

Affected products

1

Patches

1
be213bd35287

Add safety checks for grid dimension overflow in expand and prepend methods

https://github.com/becheran/gridbecheranApr 20, 2026via ghsa
2 files changed · +84 12
  • README.md+12 0 modified
    @@ -15,5 +15,17 @@ To use *grid* with *no_std* import the library such as:
     grid = { version = "*", default-features = false }
     ```
     
    +## Safety checks
    +
    +The CI in [.github/workflows/rust.yml](.github/workflows/rust.yml) runs the test suite under Miri to catch undefined behavior in exercised code paths.
    +
    +To run the same check locally:
    +
    +``` sh
    +rustup toolchain install nightly --component miri
    +cargo +nightly miri setup
    +cargo +nightly miri test --verbose
    +```
    +
     - [documentation](https://docs.rs/grid/latest/grid/)
     - [library on crates.io](https://crates.io/crates/grid)
    
  • src/lib.rs+72 12 modified
    @@ -504,6 +504,18 @@ impl<T> Grid<T> {
             }
         }
     
    +    #[inline]
    +    #[must_use]
    +    fn safe_add(lhs: usize, rhs: usize) -> usize {
    +        lhs.checked_add(rhs).expect("grid dimensions overflow")
    +    }
    +
    +    #[inline]
    +    #[must_use]
    +    fn safe_multiply(rows: usize, cols: usize) -> usize {
    +        rows.checked_mul(cols).expect("grid dimensions overflow")
    +    }
    +
         /// Returns the index of the coordinates in the internal vector.
         #[inline]
         #[must_use]
    @@ -1746,8 +1758,9 @@ impl<T: Default> Grid<T> {
         /// This method will be significantly slower if the grid uses a column-major memory layout.
         pub fn expand_rows(&mut self, rows: usize) {
             if rows > 0 && self.cols > 0 {
    -            self.data
    -                .resize_with(self.data.len() + rows * self.cols, T::default);
    +            let new_rows = Self::safe_add(self.rows, rows);
    +            let new_len = Self::safe_multiply(new_rows, self.cols);
    +            self.data.resize_with(new_len, T::default);
     
                 if self.order == Order::ColumnMajor {
                     for row_added in 0..rows {
    @@ -1758,7 +1771,7 @@ impl<T: Default> Grid<T> {
                         }
                     }
                 }
    -            self.rows += rows;
    +            self.rows = new_rows;
             }
         }
     
    @@ -1783,8 +1796,9 @@ impl<T: Default> Grid<T> {
         /// This method will be significantly slower if the grid uses a row-major memory layout.
         pub fn expand_cols(&mut self, cols: usize) {
             if cols > 0 && self.rows > 0 {
    -            self.data
    -                .resize_with(self.data.len() + cols * self.rows, T::default);
    +            let new_cols = Self::safe_add(self.cols, cols);
    +            let new_len = Self::safe_multiply(self.rows, new_cols);
    +            self.data.resize_with(new_len, T::default);
     
                 if self.order == Order::RowMajor {
                     for col_added in 0..cols {
    @@ -1795,7 +1809,7 @@ impl<T: Default> Grid<T> {
                         }
                     }
                 }
    -            self.cols += cols;
    +            self.cols = new_cols;
             }
         }
     
    @@ -1822,8 +1836,9 @@ impl<T: Default> Grid<T> {
         /// This method will be significantly slower if the grid uses a column-major memory layout.
         pub fn prepend_rows(&mut self, rows: usize) {
             if rows > 0 && self.cols > 0 {
    -            self.data
    -                .resize_with(self.data.len() + rows * self.cols, T::default);
    +            let new_rows = Self::safe_add(self.rows, rows);
    +            let new_len = Self::safe_multiply(new_rows, self.cols);
    +            self.data.resize_with(new_len, T::default);
     
                 match self.order {
                     Order::RowMajor => {
    @@ -1843,7 +1858,7 @@ impl<T: Default> Grid<T> {
                         }
                     }
                 }
    -            self.rows += rows;
    +            self.rows = new_rows;
             }
         }
     
    @@ -1868,8 +1883,9 @@ impl<T: Default> Grid<T> {
         /// This method will be significantly slower if the grid uses a row-major memory layout.
         pub fn prepend_cols(&mut self, cols: usize) {
             if cols > 0 && self.rows > 0 {
    -            self.data
    -                .resize_with(self.data.len() + cols * self.rows, T::default);
    +            let new_cols = Self::safe_add(self.cols, cols);
    +            let new_len = Self::safe_multiply(self.rows, new_cols);
    +            self.data.resize_with(new_len, T::default);
     
                 match self.order {
                     Order::RowMajor => {
    @@ -1889,7 +1905,7 @@ impl<T: Default> Grid<T> {
                         }
                     }
                 }
    -            self.cols += cols;
    +            self.cols = new_cols;
             }
         }
     }
    @@ -2891,6 +2907,50 @@ mod test {
             assert_eq!(grid.into_vec(), vec![1, 1, 1]);
         }
     
    +    fn assert_growth_overflow_keeps_grid_valid(grow: impl FnOnce(&mut Grid<u8>)) {
    +        let mut grid = Grid::from_vec_with_order(vec![1, 2], 2, Order::RowMajor);
    +
    +        let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| grow(&mut grid)));
    +
    +        assert!(result.is_err());
    +        assert_eq!(grid.size(), (1, 2));
    +        assert_eq!(grid.get(0, 0), Some(&1));
    +        assert_eq!(grid.get(0, 1), Some(&2));
    +        assert_eq!(grid.get(1, 0), None);
    +    }
    +
    +    #[test]
    +    fn expand_rows_overflow_keeps_grid_valid() {
    +        assert_growth_overflow_keeps_grid_valid(|grid| grid.expand_rows(usize::MAX / 2));
    +    }
    +
    +    #[test]
    +    fn expand_rows_overflow_safe_get_regression() {
    +        let mut grid = Grid::from_vec(vec![1_u8, 2_u8], 2);
    +
    +        let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    +            grid.expand_rows(usize::MAX / 2);
    +        }));
    +
    +        assert!(result.is_err());
    +        assert_eq!(grid.get(0, 0), Some(&1));
    +    }
    +
    +    #[test]
    +    fn expand_cols_overflow_keeps_grid_valid() {
    +        assert_growth_overflow_keeps_grid_valid(|grid| grid.expand_cols(usize::MAX));
    +    }
    +
    +    #[test]
    +    fn prepend_rows_overflow_keeps_grid_valid() {
    +        assert_growth_overflow_keeps_grid_valid(|grid| grid.prepend_rows(usize::MAX / 2));
    +    }
    +
    +    #[test]
    +    fn prepend_cols_overflow_keeps_grid_valid() {
    +        assert_growth_overflow_keeps_grid_valid(|grid| grid.prepend_cols(usize::MAX));
    +    }
    +
         #[test]
         fn expand_rows_empty_grid() {
             let mut grid: Grid<u8> = Grid::init(0, 0, 0);
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.