diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 4b124b5a3b38..6dcc299c3403 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1017,7 +1017,7 @@ impl Box { /// resulting `Box`. Specifically, the `Box` destructor will call /// the destructor of `T` and free the allocated memory. For this /// to be safe, the memory must have been allocated in accordance - /// with the [memory layout] used by `Box` . + /// with the [memory layout] used by `Box`. /// /// # Safety /// @@ -1056,8 +1056,25 @@ impl Box { #[stable(feature = "box_raw", since = "1.4.0")] #[inline] #[must_use = "call `drop(Box::from_raw(ptr))` if you intend to drop the `Box`"] - pub unsafe fn from_raw(raw: *mut T) -> Self { - unsafe { Self::from_raw_in(raw, Global) } + pub unsafe fn from_raw(ptr: *mut T) -> Self { + core::assert_unsafe_precondition!( + check_language_ub, + "Box::from_raw requires that its pointer argument is properly aligned and not null", + ( + ptr: *const () = ptr as *const (), + align: usize = align_of::(), + ) => core::intrinsics::const_eval_select!( + @capture { ptr: *const (), align: usize } -> bool: + if const { + !ptr.is_null() + } else { + ptr.is_aligned_to(align) && !ptr.is_null() + } + ) + ); + + //assert_pointer_is_aligned_and_not_null!("Box::from_raw", ptr, align_of::(), T::IS_ZST); + unsafe { Self::from_raw_in(ptr, Global) } } /// Constructs a box from a `NonNull` pointer. @@ -1111,6 +1128,12 @@ impl Box { #[inline] #[must_use = "call `drop(Box::from_non_null(ptr))` if you intend to drop the `Box`"] pub unsafe fn from_non_null(ptr: NonNull) -> Self { + /*assert_pointer_is_aligned_and_not_null!( + "Box::from_non_null", + ptr, + align_of::(), + T::IS_ZST + );*/ unsafe { Self::from_raw(ptr.as_ptr()) } } } @@ -1166,8 +1189,14 @@ impl Box { #[unstable(feature = "allocator_api", issue = "32838")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { - Box(unsafe { Unique::new_unchecked(raw) }, alloc) + pub const unsafe fn from_raw_in(ptr: *mut T, alloc: A) -> Self { + /*assert_pointer_is_aligned_and_not_null!( + "Box::from_raw_in", + ptr, + align_of::(), + T::IS_ZST + );*/ + Box(unsafe { Unique::new_unchecked(ptr) }, alloc) } /// Constructs a box from a `NonNull` pointer in the given allocator. diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index b16d40e988e1..87005dab87bf 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -154,6 +154,7 @@ #![feature(try_trait_v2)] #![feature(try_with_capacity)] #![feature(tuple_trait)] +#![feature(ub_checks)] #![feature(unicode_internals)] #![feature(unsize)] #![feature(unwrap_infallible)] diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 99c42f3626e7..c73caa17aa86 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3839,7 +3839,7 @@ where /// markes as `#[inline]`. /// /// See [`const_eval_select()`] for the rules and requirements around that intrinsic. -pub(crate) macro const_eval_select { +pub macro const_eval_select { ( @capture$([$($binders:tt)*])? { $($arg:ident : $ty:ty = $val:expr),* $(,)? } $( -> $ret:ty )? : if const @@ -4169,7 +4169,7 @@ pub const fn size_of() -> usize { #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] -pub const fn min_align_of() -> usize { +pub const fn min_align_of() -> usize { unreachable!() } diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index b9bb6d6a13f7..de8d599cafcf 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -463,7 +463,7 @@ pub fn min_align_of_val(val: &T) -> usize { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] #[rustc_const_stable(feature = "const_align_of", since = "1.24.0")] -pub const fn align_of() -> usize { +pub const fn align_of() -> usize { intrinsics::min_align_of::() } diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index 9eb71922218f..7cf611655c74 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -90,7 +90,7 @@ pub use intrinsics::ub_checks as check_library_ub; /// language UB checks which generally produce better errors. #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] -pub(crate) const fn check_language_ub() -> bool { +pub const fn check_language_ub() -> bool { // Only used for UB checks so we may const_eval_select. intrinsics::ub_checks() && const_eval_select!( @@ -129,6 +129,19 @@ pub(crate) const fn maybe_is_aligned_and_not_null( ) } +/// Specialized version of `assert_unsafe_precondition` for checking that a pointer is properly aligned and not null +#[macro_export] +#[unstable(feature = "ub_checks", issue = "none")] +macro_rules! assert_pointer_is_aligned_and_not_null { + ($function_name: literal, $ptr: expr, $align: expr, $is_zst: expr) => { + ::core::assert_unsafe_precondition!( + check_language_ub, + concat!($function_name, " requires that its pointer argument is properly aligned and not null"), + () => ::core::ub_checks::maybe_is_aligned_and_not_null(ptr as *const (), $align, $is_zst) + ); + } +} + #[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 };