mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Auto merge of #126556 - saethlin:layout-precondition, r=joboet
Add a precondition check for Layout::from_size_align_unchecked Ran into this while looking into https://github.com/rust-lang/miri/issues/3679. This is of course not the cause of the ICE, but the reproducer doesn't encounter a precondition check and it ought to.
This commit is contained in:
commit
982c6f8721
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::ptr::{Alignment, NonNull};
|
use crate::ptr::{Alignment, NonNull};
|
||||||
use crate::{cmp, fmt, mem};
|
use crate::{assert_unsafe_precondition, cmp, fmt, mem};
|
||||||
|
|
||||||
// While this function is used in one place and its implementation
|
// While this function is used in one place and its implementation
|
||||||
// could be inlined, the previous attempts to do so made rustc
|
// could be inlined, the previous attempts to do so made rustc
|
||||||
@ -66,12 +66,20 @@ impl Layout {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
|
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
|
||||||
pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
|
pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
|
||||||
if !align.is_power_of_two() {
|
if Layout::is_size_align_valid(size, align) {
|
||||||
return Err(LayoutError);
|
// SAFETY: Layout::is_size_align_valid checks the preconditions for this call.
|
||||||
|
unsafe { Ok(Layout { size, align: mem::transmute(align) }) }
|
||||||
|
} else {
|
||||||
|
Err(LayoutError)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SAFETY: just checked that align is a power of two.
|
const fn is_size_align_valid(size: usize, align: usize) -> bool {
|
||||||
Layout::from_size_alignment(size, unsafe { Alignment::new_unchecked(align) })
|
let Some(align) = Alignment::new(align) else { return false };
|
||||||
|
if size > Self::max_size_for_align(align) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -116,8 +124,17 @@ impl Layout {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
|
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
|
||||||
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
|
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
|
||||||
|
assert_unsafe_precondition!(
|
||||||
|
check_library_ub,
|
||||||
|
"Layout::from_size_align_unchecked requires that align is a power of 2 \
|
||||||
|
and the rounded-up allocation size does not exceed isize::MAX",
|
||||||
|
(
|
||||||
|
size: usize = size,
|
||||||
|
align: usize = align,
|
||||||
|
) => Layout::is_size_align_valid(size, align)
|
||||||
|
);
|
||||||
// SAFETY: the caller is required to uphold the preconditions.
|
// SAFETY: the caller is required to uphold the preconditions.
|
||||||
unsafe { Layout { size, align: Alignment::new_unchecked(align) } }
|
unsafe { Layout { size, align: mem::transmute(align) } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The minimum size in bytes for a memory block of this layout.
|
/// The minimum size in bytes for a memory block of this layout.
|
||||||
|
@ -1481,7 +1481,6 @@ impl<T, E> Result<T, E> {
|
|||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")]
|
#[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")]
|
||||||
pub unsafe fn unwrap_unchecked(self) -> T {
|
pub unsafe fn unwrap_unchecked(self) -> T {
|
||||||
debug_assert!(self.is_ok());
|
|
||||||
match self {
|
match self {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
// SAFETY: the safety contract must be upheld by the caller.
|
// SAFETY: the safety contract must be upheld by the caller.
|
||||||
@ -1513,7 +1512,6 @@ impl<T, E> Result<T, E> {
|
|||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")]
|
#[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")]
|
||||||
pub unsafe fn unwrap_err_unchecked(self) -> E {
|
pub unsafe fn unwrap_err_unchecked(self) -> E {
|
||||||
debug_assert!(self.is_err());
|
|
||||||
match self {
|
match self {
|
||||||
// SAFETY: the safety contract must be upheld by the caller.
|
// SAFETY: the safety contract must be upheld by the caller.
|
||||||
Ok(_) => unsafe { hint::unreachable_unchecked() },
|
Ok(_) => unsafe { hint::unreachable_unchecked() },
|
||||||
|
Loading…
Reference in New Issue
Block a user