From 7b1df49888f88374a9bf2fb9e8250f85e9072aff Mon Sep 17 00:00:00 2001 From: Jim Turner Date: Mon, 6 Dec 2021 23:53:35 -0500 Subject: [PATCH 1/2] Add tests for overflow converting slices to views --- tests/array-construct.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/array-construct.rs b/tests/array-construct.rs index c8948d1a3..420a9d925 100644 --- a/tests/array-construct.rs +++ b/tests/array-construct.rs @@ -244,6 +244,29 @@ fn deny_wraparound_uninit() { let _five_large = Array::::uninit((3, 7, 29, 36760123, 823996703)); } +#[should_panic] +#[test] +fn deny_slice_with_too_many_rows_to_arrayview2() { + let _view = ArrayView2::from(&[[0u8; 0]; usize::MAX][..]); +} + +#[should_panic] +#[test] +fn deny_slice_with_too_many_zero_sized_elems_to_arrayview2() { + let _view = ArrayView2::from(&[[(); isize::MAX as usize]; isize::MAX as usize][..]); +} + +#[should_panic] +#[test] +fn deny_slice_with_too_many_rows_to_arrayviewmut2() { + let _view = ArrayViewMut2::from(&mut [[0u8; 0]; usize::MAX][..]); +} + +#[should_panic] +#[test] +fn deny_slice_with_too_many_zero_sized_elems_to_arrayviewmut2() { + let _view = ArrayViewMut2::from(&mut [[(); isize::MAX as usize]; isize::MAX as usize][..]); +} #[test] fn maybe_uninit_1() { From a68435d3f6d2ec9b7267c0941dc79daafeb128d1 Mon Sep 17 00:00:00 2001 From: Jim Turner Date: Tue, 7 Dec 2021 00:01:33 -0500 Subject: [PATCH 2/2] Add missing checks when converting slices to views --- src/arraytraits.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/arraytraits.rs b/src/arraytraits.rs index f45c8a1bd..39a82b1ae 100644 --- a/src/arraytraits.rs +++ b/src/arraytraits.rs @@ -328,8 +328,9 @@ where /// Implementation of ArrayView2::from(&S) where S is a slice to a 2D array /// -/// **Panics** if the product of non-zero axis lengths overflows `isize` (This can only occur if A -/// is zero-sized because slices cannot contain more than `isize::MAX` number of bytes). +/// **Panics** if the product of non-zero axis lengths overflows `isize`. (This +/// can only occur if A is zero-sized or if `N` is zero, because slices cannot +/// contain more than `isize::MAX` number of bytes.) impl<'a, A, const N: usize> From<&'a [[A; N]]> for ArrayView<'a, A, Ix2> { /// Create a two-dimensional read-only array view of the data in `slice` fn from(xs: &'a [[A; N]]) -> Self { @@ -339,6 +340,11 @@ impl<'a, A, const N: usize> From<&'a [[A; N]]> for ArrayView<'a, A, Ix2> { if size_of::() == 0 { dimension::size_of_shape_checked(&dim) .expect("Product of non-zero axis lengths must not overflow isize."); + } else if N == 0 { + assert!( + xs.len() <= isize::MAX as usize, + "Product of non-zero axis lengths must not overflow isize.", + ); } // `cols * rows` is guaranteed to fit in `isize` because we checked that it fits in @@ -384,8 +390,9 @@ where /// Implementation of ArrayViewMut2::from(&S) where S is a slice to a 2D array /// -/// **Panics** if the product of non-zero axis lengths overflows `isize` (This can only occur if A -/// is zero-sized because slices cannot contain more than `isize::MAX` number of bytes). +/// **Panics** if the product of non-zero axis lengths overflows `isize`. (This +/// can only occur if `A` is zero-sized or if `N` is zero, because slices +/// cannot contain more than `isize::MAX` number of bytes.) impl<'a, A, const N: usize> From<&'a mut [[A; N]]> for ArrayViewMut<'a, A, Ix2> { /// Create a two-dimensional read-write array view of the data in `slice` fn from(xs: &'a mut [[A; N]]) -> Self { @@ -395,6 +402,11 @@ impl<'a, A, const N: usize> From<&'a mut [[A; N]]> for ArrayViewMut<'a, A, Ix2> if size_of::() == 0 { dimension::size_of_shape_checked(&dim) .expect("Product of non-zero axis lengths must not overflow isize."); + } else if N == 0 { + assert!( + xs.len() <= isize::MAX as usize, + "Product of non-zero axis lengths must not overflow isize.", + ); } // `cols * rows` is guaranteed to fit in `isize` because we checked that it fits in