diff options
| author | bors <bors@rust-lang.org> | 2018-11-05 22:20:25 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-11-05 22:20:25 +0000 |
| commit | 65e485d8f1d28102b426c9d6d82f835cd6470d3e (patch) | |
| tree | 74b98cfe9744cc783e1aaacfc309e81bda6bdfa4 /src/liballoc | |
| parent | 13dab66a6f6403f4eee092456f7f8f46199c5859 (diff) | |
| parent | d60290fc63bcc19714abb7fad2c01cf2efe91efa (diff) | |
| download | rust-65e485d8f1d28102b426c9d6d82f835cd6470d3e.tar.gz rust-65e485d8f1d28102b426c9d6d82f835cd6470d3e.zip | |
Auto merge of #54922 - murarth:rc-ub-fix, r=alexcrichton
Fix undefined behavior in Rc/Arc allocation Manually calculate allocation layout for `Rc`/`Arc` to avoid undefined behavior Closes #54908
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/rc.rs | 12 | ||||
| -rw-r--r-- | 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 be452ebb45a..45f035ad04f 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -668,15 +668,17 @@ impl Rc<dyn Any> { impl<T: ?Sized> Rc<T> { // Allocates an `RcBox<T>` with sufficient space for an unsized value unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> { - // Create a fake RcBox to find allocation size and alignment - let fake_ptr = ptr as *mut RcBox<T>; - - let layout = Layout::for_value(&*fake_ptr); + // Calculate layout using the given value. + // Previously, layout was calculated on the expression + // `&*(ptr as *const RcBox<T>)`, but this created a misaligned + // reference (see #54908). + let (layout, _) = Layout::new::<RcBox<()>>() + .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<T>; ptr::write(&mut (*inner).strong, Cell::new(1)); diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index d388f76d8e8..2c396b3b06b 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -571,15 +571,17 @@ impl<T: ?Sized> Arc<T> { impl<T: ?Sized> Arc<T> { // Allocates an `ArcInner<T>` with sufficient space for an unsized value unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> { - // Create a fake ArcInner to find allocation size and alignment - let fake_ptr = ptr as *mut ArcInner<T>; - - let layout = Layout::for_value(&*fake_ptr); + // Calculate layout using the given value. + // Previously, layout was calculated on the expression + // `&*(ptr as *const ArcInner<T>)`, but this created a misaligned + // reference (see #54908). + let (layout, _) = Layout::new::<ArcInner<()>>() + .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<T>; ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1)); |
