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

`}

`