diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 75d42edbaa033..e48a516aabc01 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1235,6 +1235,17 @@ pub trait SizedTypeProperties: Sized { #[doc(hidden)] #[unstable(feature = "sized_type_properties", issue = "none")] const IS_ZST: bool = size_of::() == 0; + + /// The largest safe length for a `[Self]`. + /// + /// Anything larger than this would make `size_of_val` overflow `isize::MAX`, + /// which is never allowed for a single object. + #[doc(hidden)] + #[unstable(feature = "sized_type_properties", issue = "none")] + const MAX_SLICE_LEN: usize = match size_of::() { + 0 => usize::MAX, + n => (isize::MAX as usize) / n, + }; } #[doc(hidden)] #[unstable(feature = "sized_type_properties", issue = "none")] diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 29a12f106c5ed..ef29dafbfe0d2 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -1,7 +1,8 @@ //! Free functions to create `&[T]` and `&mut [T]`. use crate::array; -use crate::mem::{align_of, size_of}; +use crate::intrinsics; +use crate::mem::{align_of, SizedTypeProperties}; use crate::ops::Range; use crate::ptr; use crate::ub_checks; @@ -98,13 +99,14 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] "slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", ( data: *mut () = data as *mut (), - size: usize = size_of::(), align: usize = align_of::(), len: usize = len, + max_len: usize = T::MAX_SLICE_LEN, ) => ub_checks::is_aligned_and_not_null(data, align) - && ub_checks::is_valid_allocation_size(size, len) + && len <= max_len ); + intrinsics::assume(len <= T::MAX_SLICE_LEN); &*ptr::slice_from_raw_parts(data, len) } } @@ -152,13 +154,14 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m "slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", ( data: *mut () = data as *mut (), - size: usize = size_of::(), align: usize = align_of::(), len: usize = len, + max_len: usize = T::MAX_SLICE_LEN, ) => ub_checks::is_aligned_and_not_null(data, align) - && ub_checks::is_valid_allocation_size(size, len) + && len <= max_len ); + intrinsics::assume(len <= T::MAX_SLICE_LEN); &mut *ptr::slice_from_raw_parts_mut(data, len) } } diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index ff6b2d3053956..354afe2113c8f 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -115,12 +115,6 @@ pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize) -> boo !ptr.is_null() && ptr.is_aligned_to(align) } -#[inline] -pub(crate) const fn is_valid_allocation_size(size: usize, len: usize) -> bool { - let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size }; - len <= max_len -} - /// Checks whether the regions of memory starting at `src` and `dst` of size /// `count * size` do *not* overlap. ///