Skip to content

Commit 1d3bc4e

Browse files
committed
Changed Layout::from_size_align to return Option.
Added `unwrap` calls in all the places where I can infer that the conditions are met to avoid panic (or when the calling method itself says it will panic in such a case).
1 parent 066fafe commit 1d3bc4e

File tree

1 file changed

+43
-19
lines changed

1 file changed

+43
-19
lines changed

src/liballoc/allocator.rs

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,21 @@ pub struct Layout {
6363
// overflowing_mul as necessary).
6464

6565
impl Layout {
66-
/// Constructs a `Layout` from a given `size` and `align`.
67-
///
68-
/// # Panics
69-
///
70-
/// Panics if any of the following conditions are not met:
66+
/// Constructs a `Layout` from a given `size` and `align`,
67+
/// or returns `None` if either of the following conditions
68+
/// are not met:
7169
///
7270
/// * `align` must be a power of two,
7371
///
7472
/// * `size`, when rounded up to the nearest multiple of `align`,
7573
/// must not overflow (i.e. the rounded value must be less than
7674
/// `usize::MAX`).
77-
pub fn from_size_align(size: usize, align: usize) -> Layout {
78-
assert!(align.is_power_of_two()); // (this implies align != 0.)
75+
pub fn from_size_align(size: usize, align: usize) -> Option<Layout> {
76+
if !align.is_power_of_two() {
77+
return None;
78+
}
79+
80+
// (power-of-two implies align != 0.)
7981

8082
// Rounded up size is:
8183
// size_rounded_up = (size + align - 1) & !(align - 1);
@@ -89,9 +91,11 @@ impl Layout {
8991
//
9092
// Above implies that checking for summation overflow is both
9193
// necessary and sufficient.
92-
assert!(size <= usize::MAX - (align - 1));
94+
if size > usize::MAX - (align - 1) {
95+
return None;
96+
}
9397

94-
Layout { size: size, align: align }
98+
Some(Layout { size: size, align: align })
9599
}
96100

97101
/// The minimum size in bytes for a memory block of this layout.
@@ -103,15 +107,15 @@ impl Layout {
103107
/// Constructs a `Layout` suitable for holding a value of type `T`.
104108
pub fn new<T>() -> Self {
105109
let (size, align) = size_align::<T>();
106-
Layout::from_size_align(size, align)
110+
Layout::from_size_align(size, align).unwrap()
107111
}
108112

109113
/// Produces layout describing a record that could be used to
110114
/// allocate backing structure for `T` (which could be a trait
111115
/// or other unsized type like a slice).
112116
pub fn for_value<T: ?Sized>(t: &T) -> Self {
113117
let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
114-
Layout::from_size_align(size, align)
118+
Layout::from_size_align(size, align).unwrap()
115119
}
116120

117121
/// Creates a layout describing the record that can hold a value
@@ -128,10 +132,10 @@ impl Layout {
128132
///
129133
/// # Panics
130134
///
131-
/// Panics if `align` is not a power of two.
135+
/// Panics if the combination of `self.size` and the given `align`
136+
/// violates the conditions listed in `from_size_align`.
132137
pub fn align_to(&self, align: usize) -> Self {
133-
assert!(align.is_power_of_two());
134-
Layout::from_size_align(self.size, cmp::max(self.align, align))
138+
Layout::from_size_align(self.size, cmp::max(self.align, align)).unwrap()
135139
}
136140

137141
/// Returns the amount of padding we must insert after `self`
@@ -193,7 +197,12 @@ impl Layout {
193197
None => return None,
194198
Some(alloc_size) => alloc_size,
195199
};
196-
Some((Layout::from_size_align(alloc_size, self.align), padded_size))
200+
201+
// We can assume that `self.align` is a power-of-two.
202+
// Furthermore, `alloc_size` has alreayd been rounded up
203+
// to a multiple of `self.align`; therefore, the call
204+
// to `Layout::from_size_align` below should never panic.
205+
Some((Layout::from_size_align(alloc_size, self.align).unwrap(), padded_size))
197206
}
198207

199208
/// Creates a layout describing the record for `self` followed by
@@ -209,8 +218,13 @@ impl Layout {
209218
/// On arithmetic overflow, returns `None`.
210219
pub fn extend(&self, next: Self) -> Option<(Self, usize)> {
211220
let new_align = cmp::max(self.align, next.align);
212-
let realigned = Layout::from_size_align(self.size, new_align);
221+
let realigned = match Layout::from_size_align(self.size, new_align) {
222+
None => return None,
223+
Some(l) => l,
224+
};
225+
213226
let pad = realigned.padding_needed_for(next.align);
227+
214228
let offset = match self.size.checked_add(pad) {
215229
None => return None,
216230
Some(offset) => offset,
@@ -219,7 +233,12 @@ impl Layout {
219233
None => return None,
220234
Some(new_size) => new_size,
221235
};
222-
Some((Layout::from_size_align(new_size, new_align), offset))
236+
237+
let layout = match Layout::from_size_align(new_size, new_align) {
238+
None => return None,
239+
Some(l) => l,
240+
};
241+
Some((layout, offset))
223242
}
224243

225244
/// Creates a layout describing the record for `n` instances of
@@ -239,7 +258,8 @@ impl Layout {
239258
None => return None,
240259
Some(scaled) => scaled,
241260
};
242-
Some(Layout::from_size_align(size, self.align))
261+
262+
Layout::from_size_align(size, self.align)
243263
}
244264

245265
/// Creates a layout describing the record for `self` followed by
@@ -262,7 +282,11 @@ impl Layout {
262282
None => return None,
263283
Some(new_size) => new_size,
264284
};
265-
Some((Layout::from_size_align(new_size, self.align), self.size()))
285+
let layout = match Layout::from_size_align(new_size, self.align) {
286+
None => return None,
287+
Some(l) => l,
288+
};
289+
Some((layout, self.size()))
266290
}
267291

268292
/// Creates a layout describing the record for a `[T; n]`.

0 commit comments

Comments
 (0)