From cfcb0a2135da6d4bdbf5f28806dea0cc70c5b6c5 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 20 Oct 2022 00:30:00 -0400 Subject: [PATCH] Use a faster allocation size check in slice::from_raw_parts --- library/core/src/intrinsics.rs | 10 ++++++++++ library/core/src/lib.rs | 1 + library/core/src/slice/raw.rs | 10 +++++----- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 2399262c05b46..3a7a179c98be9 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2229,6 +2229,16 @@ pub(crate) fn is_aligned_and_not_null(ptr: *const T) -> bool { !ptr.is_null() && ptr.is_aligned() } +/// Checks whether an allocation of `len` instances of `T` exceeds +/// the maximum allowed allocation size. +pub(crate) fn is_valid_allocation_size(len: usize) -> bool { + let max_len = const { + let size = crate::mem::size_of::(); + 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_of::()` do *not* overlap. pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) -> bool { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 2fd8180f8b2a2..aa197c990b20b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -191,6 +191,7 @@ #![feature(extern_types)] #![feature(fundamental)] #![feature(if_let_guard)] +#![feature(inline_const)] #![feature(intra_doc_pointers)] #![feature(intrinsics)] #![feature(lang_items)] diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 3c5abd215a4b7..dace748fed455 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -1,7 +1,9 @@ //! Free functions to create `&[T]` and `&mut [T]`. use crate::array; -use crate::intrinsics::{assert_unsafe_precondition, is_aligned_and_not_null}; +use crate::intrinsics::{ + assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size, +}; use crate::ops::Range; use crate::ptr; @@ -91,8 +93,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] // SAFETY: the caller must uphold the safety contract for `from_raw_parts`. unsafe { assert_unsafe_precondition!([T](data: *const T, len: usize) => - is_aligned_and_not_null(data) - && crate::mem::size_of::().saturating_mul(len) <= isize::MAX as usize + is_aligned_and_not_null(data) && is_valid_allocation_size::(len) ); &*ptr::slice_from_raw_parts(data, len) } @@ -135,8 +136,7 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`. unsafe { assert_unsafe_precondition!([T](data: *mut T, len: usize) => - is_aligned_and_not_null(data) - && crate::mem::size_of::().saturating_mul(len) <= isize::MAX as usize + is_aligned_and_not_null(data) && is_valid_allocation_size::(len) ); &mut *ptr::slice_from_raw_parts_mut(data, len) }