Skip to content

Commit 214e98d

Browse files
committed
Auto merge of #126556 - saethlin:layout-precondition, r=<try>
Add a precondition check for Layout::from_size_align_unchecked Ran into this while looking into rust-lang/miri#3679. This is of course not the cause of the ICE, but the reproducer doesn't encounter a precondition check and it ought to.
2 parents 8814b92 + 31f0305 commit 214e98d

File tree

3 files changed

+17
-4
lines changed

3 files changed

+17
-4
lines changed

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
#![feature(maybe_uninit_uninit_array_transpose)]
139139
#![feature(panic_internals)]
140140
#![feature(pattern)]
141+
#![feature(ptr_alignment_type)]
141142
#![feature(ptr_internals)]
142143
#![feature(ptr_metadata)]
143144
#![feature(ptr_sub_ptr)]

library/alloc/src/raw_vec.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use core::alloc::LayoutError;
44
use core::cmp;
55
use core::hint;
66
use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
7-
use core::ptr::{self, NonNull, Unique};
7+
use core::ptr::{self, Alignment, NonNull, Unique};
88

99
#[cfg(not(no_global_oom_handling))]
1010
use crate::alloc::handle_alloc_error;
@@ -306,9 +306,9 @@ impl<T, A: Allocator> RawVec<T, A> {
306306
// support such types. So we can do better by skipping some checks and avoid an unwrap.
307307
const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
308308
unsafe {
309-
let align = mem::align_of::<T>();
309+
let align = Alignment::of::<T>();
310310
let size = mem::size_of::<T>().unchecked_mul(self.cap.0);
311-
let layout = Layout::from_size_align_unchecked(size, align);
311+
let layout = Layout::from_size_alignment(size, align).unwrap_unchecked();
312312
Some((self.ptr.cast().into(), layout))
313313
}
314314
}

library/core/src/alloc/layout.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// collections, resulting in having to optimize down excess IR multiple times.
55
// Your performance intuition is useless. Run perf.
66

7+
use crate::assert_unsafe_precondition;
78
use crate::cmp;
89
use crate::error::Error;
910
use crate::fmt;
@@ -96,8 +97,10 @@ impl Layout {
9697
}
9798

9899
/// Internal helper constructor to skip revalidating alignment validity.
100+
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
101+
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
99102
#[inline]
100-
const fn from_size_alignment(size: usize, align: Alignment) -> Result<Self, LayoutError> {
103+
pub const fn from_size_alignment(size: usize, align: Alignment) -> Result<Self, LayoutError> {
101104
if size > Self::max_size_for_align(align) {
102105
return Err(LayoutError);
103106
}
@@ -118,6 +121,15 @@ impl Layout {
118121
#[inline]
119122
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
120123
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
124+
assert_unsafe_precondition!(
125+
check_library_ub,
126+
"Layout::from_size_align_unchecked requires that align is a power of 2 \
127+
and the rounded-up allocation size does not exceed isize::MAX",
128+
(
129+
size: usize = size,
130+
align: usize = align,
131+
) => Layout::from_size_align(size, align).is_ok()
132+
);
121133
// SAFETY: the caller is required to uphold the preconditions.
122134
unsafe { Layout { size, align: Alignment::new_unchecked(align) } }
123135
}

0 commit comments

Comments
 (0)