From 1975b8d21b21d5ede54494d0b7661d6ac14ec6a2 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Wed, 29 Aug 2018 17:20:17 +0200 Subject: [PATCH 1/7] Document that slices cannot be larger than `isize::MAX` bytes Fixes #53676. --- src/libcore/slice/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 62adaea168a3f..7f623486cdf08 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3851,6 +3851,9 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { /// them from other data. You can obtain a pointer that is usable as `data` /// for zero-length slices using [`NonNull::dangling()`]. /// +/// The total size of the slice must be no larger than `isize::MAX` **bytes** +/// in memory. See the safety documentation of [`pointer::offset`]. +/// /// # Caveat /// /// The lifetime for the returned slice is inferred from its usage. To @@ -3872,6 +3875,7 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { /// ``` /// /// [`NonNull::dangling()`]: ../../std/ptr/struct.NonNull.html#method.dangling +/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { From 7b77508e233c724bcaf9821f62dbe45dc4b4cdb3 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 4 Sep 2018 11:22:25 +0200 Subject: [PATCH 2/7] Add `debug_assert!`s to `slice::from_raw_parts` Copy the documentation over to `slice::from_raw_parts_mut`. --- src/libcore/slice/mod.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 7f623486cdf08..44d2243c2ccd5 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -34,6 +34,7 @@ use cmp::Ordering::{self, Less, Equal, Greater}; use cmp; use fmt; use intrinsics::assume; +use isize; use iter::*; use ops::{FnMut, Try, self}; use option::Option; @@ -3880,6 +3881,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); + debug_assert!(len * mem::size_of::() <= isize::MAX as usize, + "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len } }.rust } @@ -3889,14 +3892,20 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { /// This function is unsafe for the same reasons as [`from_raw_parts`], as well /// as not being able to provide a non-aliasing guarantee of the returned /// mutable slice. `data` must be non-null and aligned even for zero-length -/// slices as with [`from_raw_parts`]. See the documentation of -/// [`from_raw_parts`] for more details. +/// slices as with [`from_raw_parts`]. The total size of the slice must be no +/// larger than `isize::MAX` **bytes** in memory. See the safety documentation +/// of [`pointer::offset`]. +/// +/// See the documentation of [`from_raw_parts`] for more details. /// /// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html +/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); + debug_assert!(len * mem::size_of::() <= isize::MAX as usize, + "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len} }.rust_mut } From 1aac00fad391d7f714be1401992e95d5dffcb300 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 10 Sep 2018 07:53:42 +0200 Subject: [PATCH 3/7] A slice covering exactly half the address space is not OK --- src/libcore/slice/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 44d2243c2ccd5..7fd8e2599f988 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3852,8 +3852,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { /// them from other data. You can obtain a pointer that is usable as `data` /// for zero-length slices using [`NonNull::dangling()`]. /// -/// The total size of the slice must be no larger than `isize::MAX` **bytes** -/// in memory. See the safety documentation of [`pointer::offset`]. +/// The total size of the slice must lower than `isize::MAX` **bytes** in +/// memory. See the safety documentation of [`pointer::offset`]. /// /// # Caveat /// @@ -3881,7 +3881,7 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); - debug_assert!(len * mem::size_of::() <= isize::MAX as usize, + debug_assert!(len * mem::size_of::() < isize::MAX as usize, "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len } }.rust } @@ -3892,8 +3892,8 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { /// This function is unsafe for the same reasons as [`from_raw_parts`], as well /// as not being able to provide a non-aliasing guarantee of the returned /// mutable slice. `data` must be non-null and aligned even for zero-length -/// slices as with [`from_raw_parts`]. The total size of the slice must be no -/// larger than `isize::MAX` **bytes** in memory. See the safety documentation +/// slices as with [`from_raw_parts`]. The total size of the slice must be +/// lower than `isize::MAX` **bytes** in memory. See the safety documentation /// of [`pointer::offset`]. /// /// See the documentation of [`from_raw_parts`] for more details. @@ -3904,7 +3904,7 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); - debug_assert!(len * mem::size_of::() <= isize::MAX as usize, + debug_assert!(len * mem::size_of::() < isize::MAX as usize, "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len} }.rust_mut } From 5d9086f12361fc1dc51d831497a9af68046eb2d1 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 11 Sep 2018 11:44:28 +0200 Subject: [PATCH 4/7] Fix overflow in `from_raw_parts` size check --- src/libcore/slice/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 7fd8e2599f988..e7e4789e09f49 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3881,7 +3881,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); - debug_assert!(len * mem::size_of::() < isize::MAX as usize, + let size = mem::size_of::(); + debug_assert!(size == 0 || len < (isize::MAX as usize + size - 1) / size, "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len } }.rust } @@ -3904,9 +3905,10 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); - debug_assert!(len * mem::size_of::() < isize::MAX as usize, + let size = mem::size_of::(); + debug_assert!(size == 0 || len < (isize::MAX as usize + size - 1) / size, "attempt to create slice covering half the address space"); - Repr { raw: FatPtr { data, len} }.rust_mut + Repr { raw: FatPtr { data, len } }.rust_mut } /// Converts a reference to T into a slice of length 1 (without copying). From 11c631838067927cddb4c867089401ae7f9ffb8b Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 17 Sep 2018 18:09:04 +0200 Subject: [PATCH 5/7] Use more obvious calculation for slice size check --- src/libcore/slice/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index e7e4789e09f49..3f43da9b3b6fa 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3881,8 +3881,7 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); - let size = mem::size_of::(); - debug_assert!(size == 0 || len < (isize::MAX as usize + size - 1) / size, + debug_assert!(mem::size_of::().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len } }.rust } @@ -3905,8 +3904,7 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); - let size = mem::size_of::(); - debug_assert!(size == 0 || len < (isize::MAX as usize + size - 1) / size, + debug_assert!(mem::size_of::().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len } }.rust_mut } From ebffb672950dbf6d2a19364269f95b4bc3e40dc4 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 17 Sep 2018 18:34:15 +0200 Subject: [PATCH 6/7] Adjust the docs of `from_raw_parts` to match the implementation --- src/libcore/slice/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 3f43da9b3b6fa..0a719792c7f85 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3852,8 +3852,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { /// them from other data. You can obtain a pointer that is usable as `data` /// for zero-length slices using [`NonNull::dangling()`]. /// -/// The total size of the slice must lower than `isize::MAX` **bytes** in -/// memory. See the safety documentation of [`pointer::offset`]. +/// The total size of the slice must be no larger than `isize::MAX` **bytes** +/// in memory. See the safety documentation of [`pointer::offset`]. /// /// # Caveat /// @@ -3892,8 +3892,8 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { /// This function is unsafe for the same reasons as [`from_raw_parts`], as well /// as not being able to provide a non-aliasing guarantee of the returned /// mutable slice. `data` must be non-null and aligned even for zero-length -/// slices as with [`from_raw_parts`]. The total size of the slice must be -/// lower than `isize::MAX` **bytes** in memory. See the safety documentation +/// slices as with [`from_raw_parts`]. The total size of the slice must be no +/// larger than `isize::MAX` **bytes** in memory. See the safety documentation /// of [`pointer::offset`]. /// /// See the documentation of [`from_raw_parts`] for more details. From e370b1ccaed1f2775e2d944acc2898c98b415083 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Thu, 27 Sep 2018 09:49:12 +0200 Subject: [PATCH 7/7] Don't have two adjacent "see also" sentences --- src/libcore/slice/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 0a719792c7f85..a76b30260369d 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3893,13 +3893,11 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { /// as not being able to provide a non-aliasing guarantee of the returned /// mutable slice. `data` must be non-null and aligned even for zero-length /// slices as with [`from_raw_parts`]. The total size of the slice must be no -/// larger than `isize::MAX` **bytes** in memory. See the safety documentation -/// of [`pointer::offset`]. +/// larger than `isize::MAX` **bytes** in memory. /// /// See the documentation of [`from_raw_parts`] for more details. /// /// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html -/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {