|
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,20 @@ 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 | + unsafe { Ok(Layout { size, align: mem::transmute(align) }) } |
| 72 | + } else { |
| 73 | + Err(LayoutError) |
71 | 74 | }
|
| 75 | + } |
72 | 76 |
|
73 |
| - // SAFETY: just checked that align is a power of two. |
74 |
| - Layout::from_size_alignment(size, unsafe { Alignment::new_unchecked(align) }) |
| 77 | + const fn is_size_align_valid(size: usize, align: usize) -> bool { |
| 78 | + let Some(align) = Alignment::new(align) else { return false }; |
| 79 | + if size > Self::max_size_for_align(align) { |
| 80 | + return false; |
| 81 | + } |
| 82 | + true |
75 | 83 | }
|
76 | 84 |
|
77 | 85 | #[inline(always)]
|
@@ -116,8 +124,17 @@ impl Layout {
|
116 | 124 | #[inline]
|
117 | 125 | #[rustc_allow_const_fn_unstable(ptr_alignment_type)]
|
118 | 126 | pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
|
| 127 | + assert_unsafe_precondition!( |
| 128 | + check_library_ub, |
| 129 | + "Layout::from_size_align_unchecked requires that align is a power of 2 \ |
| 130 | + and the rounded-up allocation size does not exceed isize::MAX", |
| 131 | + ( |
| 132 | + size: usize = size, |
| 133 | + align: usize = align, |
| 134 | + ) => Layout::is_size_align_valid(size, align) |
| 135 | + ); |
119 | 136 | // SAFETY: the caller is required to uphold the preconditions.
|
120 |
| - unsafe { Layout { size, align: Alignment::new_unchecked(align) } } |
| 137 | + unsafe { Layout { size, align: mem::transmute(align) } } |
121 | 138 | }
|
122 | 139 |
|
123 | 140 | /// The minimum size in bytes for a memory block of this layout.
|
|
0 commit comments