From d60290fc63bcc19714abb7fad2c01cf2efe91efa Mon Sep 17 00:00:00 2001 From: Murarth Date: Mon, 8 Oct 2018 16:52:48 -0700 Subject: [PATCH] Fix undefined behavior in Rc/Arc allocation Manually calculate allocation layout for `Rc`/`Arc` to avoid undefined behavior --- src/liballoc/rc.rs | 12 +++++++----- src/liballoc/sync.rs | 12 +++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 915b8e7787e99..33511b8e0a1d6 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -665,15 +665,17 @@ impl Rc { impl Rc { // Allocates an `RcBox` with sufficient space for an unsized value unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox { - // Create a fake RcBox to find allocation size and alignment - let fake_ptr = ptr as *mut RcBox; - - let layout = Layout::for_value(&*fake_ptr); + // Calculate layout using the given value. + // Previously, layout was calculated on the expression + // `&*(ptr as *const RcBox)`, but this created a misaligned + // reference (see #54908). + let (layout, _) = Layout::new::>() + .extend(Layout::for_value(&*ptr)).unwrap(); let mem = Global.alloc(layout) .unwrap_or_else(|_| handle_alloc_error(layout)); - // Initialize the real RcBox + // Initialize the RcBox let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox; ptr::write(&mut (*inner).strong, Cell::new(1)); diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 9e245fbd7bbe5..7f7b8fb90e666 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -566,15 +566,17 @@ impl Arc { impl Arc { // Allocates an `ArcInner` with sufficient space for an unsized value unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner { - // Create a fake ArcInner to find allocation size and alignment - let fake_ptr = ptr as *mut ArcInner; - - let layout = Layout::for_value(&*fake_ptr); + // Calculate layout using the given value. + // Previously, layout was calculated on the expression + // `&*(ptr as *const ArcInner)`, but this created a misaligned + // reference (see #54908). + let (layout, _) = Layout::new::>() + .extend(Layout::for_value(&*ptr)).unwrap(); let mem = Global.alloc(layout) .unwrap_or_else(|_| handle_alloc_error(layout)); - // Initialize the real ArcInner + // Initialize the ArcInner let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner; ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1));