Skip to content

Commit 473848b

Browse files
committed
UB-check for alignment of ptr to Box::from_raw{,_in}
1 parent 28b83ee commit 473848b

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed

library/alloc/src/boxed.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ use core::ops::{
200200
use core::pin::{Pin, PinCoerceUnsized};
201201
use core::ptr::{self, NonNull, Unique};
202202
use core::task::{Context, Poll};
203+
use core::ub_checks::assert_pointer_is_aligned_and_not_null;
203204

204205
#[cfg(not(no_global_oom_handling))]
205206
use crate::alloc::handle_alloc_error;
@@ -1017,7 +1018,7 @@ impl<T: ?Sized> Box<T> {
10171018
/// resulting `Box`. Specifically, the `Box` destructor will call
10181019
/// the destructor of `T` and free the allocated memory. For this
10191020
/// to be safe, the memory must have been allocated in accordance
1020-
/// with the [memory layout] used by `Box` .
1021+
/// with the [memory layout] used by `Box`.
10211022
///
10221023
/// # Safety
10231024
///
@@ -1056,8 +1057,9 @@ impl<T: ?Sized> Box<T> {
10561057
#[stable(feature = "box_raw", since = "1.4.0")]
10571058
#[inline]
10581059
#[must_use = "call `drop(Box::from_raw(ptr))` if you intend to drop the `Box`"]
1059-
pub unsafe fn from_raw(raw: *mut T) -> Self {
1060-
unsafe { Self::from_raw_in(raw, Global) }
1060+
pub unsafe fn from_raw(ptr: *mut T) -> Self {
1061+
assert_pointer_is_aligned_and_not_null!(Box::from_raw, ptr, align_of::<T>(), T::IS_ZST);
1062+
unsafe { Self::from_raw_in(ptr, Global) }
10611063
}
10621064

10631065
/// Constructs a box from a `NonNull` pointer.
@@ -1111,6 +1113,12 @@ impl<T: ?Sized> Box<T> {
11111113
#[inline]
11121114
#[must_use = "call `drop(Box::from_non_null(ptr))` if you intend to drop the `Box`"]
11131115
pub unsafe fn from_non_null(ptr: NonNull<T>) -> Self {
1116+
assert_pointer_is_aligned_and_not_null!(
1117+
Box::from_non_null,
1118+
ptr,
1119+
align_of::<T>(),
1120+
T::IS_ZST
1121+
);
11141122
unsafe { Self::from_raw(ptr.as_ptr()) }
11151123
}
11161124
}
@@ -1166,8 +1174,9 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
11661174
#[unstable(feature = "allocator_api", issue = "32838")]
11671175
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
11681176
#[inline]
1169-
pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
1170-
Box(unsafe { Unique::new_unchecked(raw) }, alloc)
1177+
pub const unsafe fn from_raw_in(ptr: *mut T, alloc: A) -> Self {
1178+
assert_pointer_is_aligned_and_not_null!(Box::from_raw_in, ptr, align_of::<T>(), T::IS_ZST);
1179+
Box(unsafe { Unique::new_unchecked(ptr) }, alloc)
11711180
}
11721181

11731182
/// Constructs a box from a `NonNull` pointer in the given allocator.

library/core/src/ub_checks.rs

+13
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,19 @@ pub(crate) const fn maybe_is_aligned_and_not_null(
129129
)
130130
}
131131

132+
/// Specialized version of `assert_unsafe_precondition` for checking that a pointer is properly aligned and not null
133+
#[macro_export]
134+
#[unstable(feature = "ub_checks", issue = "none")]
135+
macro_rules! assert_pointer_is_aligned_and_not_null {
136+
($function_name: path, $ptr: expr, $align: expr, $is_zst: expr) => {
137+
assert_unsafe_precondition!(
138+
check_language_ub,
139+
format!("{} requires that its pointer argument is properly aligned and not null", $function_name),
140+
() => ub_checks::maybe_is_aligned_and_not_null(ptr as *const (), $align, $is_zst)
141+
);
142+
}
143+
}
144+
132145
#[inline]
133146
pub(crate) const fn is_valid_allocation_size(size: usize, len: usize) -> bool {
134147
let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size };

0 commit comments

Comments
 (0)