Skip to content

Commit bbd76da

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

File tree

4 files changed

+44
-7
lines changed

4 files changed

+44
-7
lines changed

library/alloc/src/boxed.rs

+28-5
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ impl<T: ?Sized> Box<T> {
10171017
/// resulting `Box`. Specifically, the `Box` destructor will call
10181018
/// the destructor of `T` and free the allocated memory. For this
10191019
/// to be safe, the memory must have been allocated in accordance
1020-
/// with the [memory layout] used by `Box` .
1020+
/// with the [memory layout] used by `Box`.
10211021
///
10221022
/// # Safety
10231023
///
@@ -1056,8 +1056,19 @@ impl<T: ?Sized> Box<T> {
10561056
#[stable(feature = "box_raw", since = "1.4.0")]
10571057
#[inline]
10581058
#[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) }
1059+
pub unsafe fn from_raw(ptr: *mut T) -> Self {
1060+
core::assert_unsafe_precondition!(
1061+
check_language_ub,
1062+
"Box::from_raw requires that its pointer argument is properly aligned and not null",
1063+
(
1064+
ptr: *const () = ptr as *const (),
1065+
align: usize = align_of::<T>(),
1066+
is_zst: bool = T::IS_ZST,
1067+
) => maybe_is_aligned_and_not_null(ptr, align, is_zst)
1068+
);
1069+
1070+
//assert_pointer_is_aligned_and_not_null!("Box::from_raw", ptr, align_of::<T>(), T::IS_ZST);
1071+
unsafe { Self::from_raw_in(ptr, Global) }
10611072
}
10621073

10631074
/// Constructs a box from a `NonNull` pointer.
@@ -1111,6 +1122,12 @@ impl<T: ?Sized> Box<T> {
11111122
#[inline]
11121123
#[must_use = "call `drop(Box::from_non_null(ptr))` if you intend to drop the `Box`"]
11131124
pub unsafe fn from_non_null(ptr: NonNull<T>) -> Self {
1125+
/*assert_pointer_is_aligned_and_not_null!(
1126+
"Box::from_non_null",
1127+
ptr,
1128+
align_of::<T>(),
1129+
T::IS_ZST
1130+
);*/
11141131
unsafe { Self::from_raw(ptr.as_ptr()) }
11151132
}
11161133
}
@@ -1166,8 +1183,14 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
11661183
#[unstable(feature = "allocator_api", issue = "32838")]
11671184
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
11681185
#[inline]
1169-
pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
1170-
Box(unsafe { Unique::new_unchecked(raw) }, alloc)
1186+
pub const unsafe fn from_raw_in(ptr: *mut T, alloc: A) -> Self {
1187+
/*assert_pointer_is_aligned_and_not_null!(
1188+
"Box::from_raw_in",
1189+
ptr,
1190+
align_of::<T>(),
1191+
T::IS_ZST
1192+
);*/
1193+
Box(unsafe { Unique::new_unchecked(ptr) }, alloc)
11711194
}
11721195

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

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
#![feature(try_trait_v2)]
155155
#![feature(try_with_capacity)]
156156
#![feature(tuple_trait)]
157+
#![feature(ub_checks)]
157158
#![feature(unicode_internals)]
158159
#![feature(unsize)]
159160
#![feature(unwrap_infallible)]

library/core/src/mem/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
463463
#[stable(feature = "rust1", since = "1.0.0")]
464464
#[rustc_promotable]
465465
#[rustc_const_stable(feature = "const_align_of", since = "1.24.0")]
466-
pub const fn align_of<T>() -> usize {
466+
pub const fn align_of<T: ?Sized>() -> usize {
467467
intrinsics::min_align_of::<T>()
468468
}
469469

library/core/src/ub_checks.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub use intrinsics::ub_checks as check_library_ub;
9090
/// language UB checks which generally produce better errors.
9191
#[inline]
9292
#[rustc_allow_const_fn_unstable(const_eval_select)]
93-
pub(crate) const fn check_language_ub() -> bool {
93+
pub const fn check_language_ub() -> bool {
9494
// Only used for UB checks so we may const_eval_select.
9595
intrinsics::ub_checks()
9696
&& const_eval_select!(
@@ -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: literal, $ptr: expr, $align: expr, $is_zst: expr) => {
137+
::core::assert_unsafe_precondition!(
138+
check_language_ub,
139+
concat!($function_name, " requires that its pointer argument is properly aligned and not null"),
140+
() => ::core::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)