Skip to content

Commit d2aeef0

Browse files
authored
Rollup merge of rust-lang#55764 - murarth:fix-rc-alloc, r=RalfJung
Fix Rc/Arc allocation layout * Rounds allocation layout up to a multiple of alignment * Adds a convenience method `Layout::pad_to_align` to perform rounding Closes rust-lang#55747 cc rust-lang#55724
2 parents f0a6e3a + 317f494 commit d2aeef0

File tree

3 files changed

+25
-4
lines changed

3 files changed

+25
-4
lines changed

src/liballoc/rc.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -672,14 +672,16 @@ impl<T: ?Sized> Rc<T> {
672672
// Previously, layout was calculated on the expression
673673
// `&*(ptr as *const RcBox<T>)`, but this created a misaligned
674674
// reference (see #54908).
675-
let (layout, _) = Layout::new::<RcBox<()>>()
676-
.extend(Layout::for_value(&*ptr)).unwrap();
675+
let layout = Layout::new::<RcBox<()>>()
676+
.extend(Layout::for_value(&*ptr)).unwrap().0
677+
.pad_to_align().unwrap();
677678

678679
let mem = Global.alloc(layout)
679680
.unwrap_or_else(|_| handle_alloc_error(layout));
680681

681682
// Initialize the RcBox
682683
let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>;
684+
debug_assert_eq!(Layout::for_value(&*inner), layout);
683685

684686
ptr::write(&mut (*inner).strong, Cell::new(1));
685687
ptr::write(&mut (*inner).weak, Cell::new(1));

src/liballoc/sync.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -575,14 +575,16 @@ impl<T: ?Sized> Arc<T> {
575575
// Previously, layout was calculated on the expression
576576
// `&*(ptr as *const ArcInner<T>)`, but this created a misaligned
577577
// reference (see #54908).
578-
let (layout, _) = Layout::new::<ArcInner<()>>()
579-
.extend(Layout::for_value(&*ptr)).unwrap();
578+
let layout = Layout::new::<ArcInner<()>>()
579+
.extend(Layout::for_value(&*ptr)).unwrap().0
580+
.pad_to_align().unwrap();
580581

581582
let mem = Global.alloc(layout)
582583
.unwrap_or_else(|_| handle_alloc_error(layout));
583584

584585
// Initialize the ArcInner
585586
let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>;
587+
debug_assert_eq!(Layout::for_value(&*inner), layout);
586588

587589
ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1));
588590
ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));

src/libcore/alloc.rs

+17
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,23 @@ impl Layout {
218218
len_rounded_up.wrapping_sub(len)
219219
}
220220

221+
/// Creates a layout by rounding the size of this layout up to a multiple
222+
/// of the layout's alignment.
223+
///
224+
/// Returns `Err` if the padded size would overflow.
225+
///
226+
/// This is equivalent to adding the result of `padding_needed_for`
227+
/// to the layout's current size.
228+
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
229+
#[inline]
230+
pub fn pad_to_align(&self) -> Result<Layout, LayoutErr> {
231+
let pad = self.padding_needed_for(self.align());
232+
let new_size = self.size().checked_add(pad)
233+
.ok_or(LayoutErr { private: () })?;
234+
235+
Layout::from_size_align(new_size, self.align())
236+
}
237+
221238
/// Creates a layout describing the record for `n` instances of
222239
/// `self`, with a suitable amount of padding between each to
223240
/// ensure that each instance is given its requested size and

0 commit comments

Comments
 (0)