Add a precondition check for Layout::from_size_align_unchecked · patricklam/verify-rust-std@bef7be0 (original) (raw)
`@@ -6,7 +6,7 @@
`
6
6
``
7
7
`use crate::error::Error;
`
8
8
`use crate::ptr::{Alignment, NonNull};
`
9
``
`-
use crate::{cmp, fmt, mem};
`
``
9
`+
use crate::{assert_unsafe_precondition, cmp, fmt, mem};
`
10
10
``
11
11
`// While this function is used in one place and its implementation
`
12
12
`// could be inlined, the previous attempts to do so made rustc
`
`@@ -66,12 +66,25 @@ impl Layout {
`
66
66
`#[inline]
`
67
67
`#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
`
68
68
`pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
`
69
``
`-
if !align.is_power_of_two() {
`
70
``
`-
return Err(LayoutError);
`
``
69
`+
if Layout::is_size_align_valid(size, align) {
`
``
70
`+
// SAFETY: Layout::is_size_align_valid checks the preconditions for this call.
`
``
71
`+
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
`
``
72
`+
Ok(layout)
`
``
73
`+
} else {
`
``
74
`+
Err(LayoutError)
`
71
75
`}
`
``
76
`+
}
`
72
77
``
73
``
`-
// SAFETY: just checked that align is a power of two.
`
74
``
`-
Layout::from_size_alignment(size, unsafe { Alignment::new_unchecked(align) })
`
``
78
`+
const fn is_size_align_valid(size: usize, align: usize) -> bool {
`
``
79
`+
if !align.is_power_of_two() {
`
``
80
`+
return false;
`
``
81
`+
}
`
``
82
`+
// SAFETY: Precondition checked directly above.
`
``
83
`+
let align = unsafe { Alignment::new_unchecked(align) };
`
``
84
`+
if size > Self::max_size_for_align(align) {
`
``
85
`+
return false;
`
``
86
`+
}
`
``
87
`+
true
`
75
88
`}
`
76
89
``
77
90
`#[inline(always)]
`
`@@ -116,6 +129,15 @@ impl Layout {
`
116
129
`#[inline]
`
117
130
`#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
`
118
131
`pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
`
``
132
`+
assert_unsafe_precondition!(
`
``
133
`+
check_library_ub,
`
``
134
`+
"Layout::from_size_align_unchecked requires that align is a power of 2 \
`
``
135
`+
and the rounded-up allocation size does not exceed isize::MAX",
`
``
136
`+
(
`
``
137
`+
size: usize = size,
`
``
138
`+
align: usize = align,
`
``
139
`+
) => Layout::is_size_align_valid(size, align)
`
``
140
`+
);
`
119
141
`// SAFETY: the caller is required to uphold the preconditions.
`
120
142
`unsafe { Layout { size, align: Alignment::new_unchecked(align) } }
`
121
143
`}
`