Skip to content

Commit f68f1cb

Browse files
committed
Enforce that layout size fits in isize in Layout
1 parent 9a9a232 commit f68f1cb

File tree

1 file changed

+34
-19
lines changed

1 file changed

+34
-19
lines changed

core/src/alloc/layout.rs

+34-19
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::cmp;
2+
use crate::convert::TryFrom;
23
use crate::fmt;
34
use crate::mem;
45
use crate::num::NonZeroUsize;
@@ -53,8 +54,8 @@ impl Layout {
5354
/// * `align` must be a power of two,
5455
///
5556
/// * `size`, when rounded up to the nearest multiple of `align`,
56-
/// must not overflow (i.e., the rounded value must be less than
57-
/// or equal to `usize::MAX`).
57+
/// must not overflow isize (i.e., the rounded value must be
58+
/// less than or equal to `isize::MAX`).
5859
#[stable(feature = "alloc_layout", since = "1.28.0")]
5960
#[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")]
6061
#[inline]
@@ -77,7 +78,7 @@ impl Layout {
7778
//
7879
// Above implies that checking for summation overflow is both
7980
// necessary and sufficient.
80-
if size > usize::MAX - (align - 1) {
81+
if size > isize::MAX as usize - (align - 1) {
8182
return Err(LayoutError);
8283
}
8384

@@ -277,8 +278,8 @@ impl Layout {
277278
let pad = self.padding_needed_for(self.align());
278279
// This cannot overflow. Quoting from the invariant of Layout:
279280
// > `size`, when rounded up to the nearest multiple of `align`,
280-
// > must not overflow (i.e., the rounded value must be less than
281-
// > `usize::MAX`)
281+
// > must not overflow isize (i.e., the rounded value must be
282+
// > less than or equal to `isize::MAX`)
282283
let new_size = self.size() + pad;
283284

284285
// SAFETY: self.align is already known to be valid and new_size has been
@@ -299,14 +300,21 @@ impl Layout {
299300
pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> {
300301
// This cannot overflow. Quoting from the invariant of Layout:
301302
// > `size`, when rounded up to the nearest multiple of `align`,
302-
// > must not overflow (i.e., the rounded value must be less than
303-
// > `usize::MAX`)
303+
// > must not overflow isize (i.e., the rounded value must be
304+
// > less than or equal to `isize::MAX`)
304305
let padded_size = self.size() + self.padding_needed_for(self.align());
305-
let alloc_size = padded_size.checked_mul(n).ok_or(LayoutError)?;
306+
// Size manipulation is done in isize space to avoid overflowing isize.
307+
let n = isize::try_from(n).map_err(|_| LayoutError)?;
308+
let alloc_size = (padded_size as isize).checked_mul(n).ok_or(LayoutError)?;
306309

307310
// SAFETY: self.align is already known to be valid and alloc_size has been
308311
// padded already.
309-
unsafe { Ok((Layout::from_size_align_unchecked(alloc_size, self.align()), padded_size)) }
312+
unsafe {
313+
Ok((
314+
Layout::from_size_align_unchecked(alloc_size as usize, self.align()),
315+
padded_size as usize,
316+
))
317+
}
310318
}
311319

312320
/// Creates a layout describing the record for `self` followed by
@@ -360,11 +368,12 @@ impl Layout {
360368
let new_align = cmp::max(self.align(), next.align());
361369
let pad = self.padding_needed_for(next.align());
362370

363-
let offset = self.size().checked_add(pad).ok_or(LayoutError)?;
364-
let new_size = offset.checked_add(next.size()).ok_or(LayoutError)?;
371+
// Size manipulation is done in isize space to avoid overflowing isize.
372+
let offset = (self.size() as isize).checked_add(pad as isize).ok_or(LayoutError)?;
373+
let new_size = offset.checked_add(next.size() as isize).ok_or(LayoutError)?;
365374

366-
let layout = Layout::from_size_align(new_size, new_align)?;
367-
Ok((layout, offset))
375+
let layout = Layout::from_size_align(new_size as usize, new_align)?;
376+
Ok((layout, offset as usize))
368377
}
369378

370379
/// Creates a layout describing the record for `n` instances of
@@ -382,8 +391,10 @@ impl Layout {
382391
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
383392
#[inline]
384393
pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutError> {
385-
let size = self.size().checked_mul(n).ok_or(LayoutError)?;
386-
Layout::from_size_align(size, self.align())
394+
// Size manipulation is done in isize space to avoid overflowing isize.
395+
let n = isize::try_from(n).map_err(|_| LayoutError)?;
396+
let size = (self.size() as isize).checked_mul(n).ok_or(LayoutError)?;
397+
Layout::from_size_align(size as usize, self.align())
387398
}
388399

389400
/// Creates a layout describing the record for `self` followed by
@@ -395,8 +406,10 @@ impl Layout {
395406
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
396407
#[inline]
397408
pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutError> {
398-
let new_size = self.size().checked_add(next.size()).ok_or(LayoutError)?;
399-
Layout::from_size_align(new_size, self.align())
409+
// Size manipulation is done in isize space to avoid overflowing isize.
410+
let new_size =
411+
(self.size() as isize).checked_add(next.size() as isize).ok_or(LayoutError)?;
412+
Layout::from_size_align(new_size as usize, self.align())
400413
}
401414

402415
/// Creates a layout describing the record for a `[T; n]`.
@@ -405,7 +418,9 @@ impl Layout {
405418
#[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
406419
#[inline]
407420
pub fn array<T>(n: usize) -> Result<Self, LayoutError> {
408-
let array_size = mem::size_of::<T>().checked_mul(n).ok_or(LayoutError)?;
421+
// Size manipulation is done in isize space to avoid overflowing isize.
422+
let n = isize::try_from(n).map_err(|_| LayoutError)?;
423+
let array_size = (mem::size_of::<T>() as isize).checked_mul(n).ok_or(LayoutError)?;
409424

410425
// SAFETY:
411426
// - Size: `array_size` cannot be too big because `size_of::<T>()` must
@@ -415,7 +430,7 @@ impl Layout {
415430
// just checked by the `checked_mul()`.
416431
// - Alignment: `align_of::<T>()` will always give an acceptable
417432
// (non-zero, power of two) alignment.
418-
Ok(unsafe { Layout::from_size_align_unchecked(array_size, mem::align_of::<T>()) })
433+
Ok(unsafe { Layout::from_size_align_unchecked(array_size as usize, mem::align_of::<T>()) })
419434
}
420435
}
421436

0 commit comments

Comments
 (0)