diff --git a/src/base/iter.rs b/src/base/iter.rs index 74e4f018..bad4e0be 100644 --- a/src/base/iter.rs +++ b/src/base/iter.rs @@ -27,12 +27,30 @@ macro_rules! iterator { let shape = storage.shape(); let strides = storage.strides(); let inner_offset = shape.0.value() * strides.0.value(); + let size = shape.0.value() * shape.1.value(); let ptr = storage.$ptr(); + // If we have a size of 0, 'ptr' must be + // dangling. Howver, 'inner_offset' might + // not be zero if only one dimension is zero, so + // we don't want to call 'offset'. + // This pointer will never actually get used + // if our size is '0', so it's fine to use + // 'ptr' for both the start and end. + let inner_end = if size == 0 { + ptr + } else { + // Safety: + // If 'size' is non-zero, we know that 'ptr' + // is not dangling, and 'inner_offset' must lie + // within the allocation + unsafe { ptr.offset(inner_offset as isize) } + }; + $Name { ptr: ptr, inner_ptr: ptr, - inner_end: unsafe { ptr.offset(inner_offset as isize) }, + inner_end, size: shape.0.value() * shape.1.value(), strides: strides, _phantoms: PhantomData, diff --git a/src/base/storage.rs b/src/base/storage.rs index 02941e47..e7439552 100644 --- a/src/base/storage.rs +++ b/src/base/storage.rs @@ -72,7 +72,7 @@ pub unsafe trait Storage: Debug + Sized { /// Gets the address of the i-th matrix component without performing bound-checking. #[inline] unsafe fn get_address_unchecked_linear(&self, i: usize) -> *const N { - self.ptr().offset(i as isize) + self.ptr().wrapping_offset(i as isize) } /// Gets the address of the i-th matrix component without performing bound-checking. @@ -124,7 +124,7 @@ pub unsafe trait StorageMut: Storage { /// Gets the mutable address of the i-th matrix component without performing bound-checking. #[inline] unsafe fn get_address_unchecked_linear_mut(&mut self, i: usize) -> *mut N { - self.ptr_mut().offset(i as isize) + self.ptr_mut().wrapping_offset(i as isize) } /// Gets the mutable address of the i-th matrix component without performing bound-checking.