about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMurarth <murarth@gmail.com>2018-11-07 10:59:25 -0700
committerMurarth <murarth@gmail.com>2018-11-08 11:50:02 -0700
commit317f494c72aead3fecd73788569983fd2f8ea8a3 (patch)
tree9ff610a28d4e52ba1301f8472d3aa7dc403aaeaf /src
parent653da4fd006c97625247acd7e076d0782cdc149b (diff)
downloadrust-317f494c72aead3fecd73788569983fd2f8ea8a3.tar.gz
rust-317f494c72aead3fecd73788569983fd2f8ea8a3.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/liballoc/rc.rs6
-rw-r--r--src/liballoc/sync.rs6
-rw-r--r--src/libcore/alloc.rs17
3 files changed, 25 insertions, 4 deletions
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 45f035ad04f..bb52d7990ff 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -672,14 +672,16 @@ impl<T: ?Sized> Rc<T> {
         // 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 layout = Layout::new::<RcBox<()>>()
+            .extend(Layout::for_value(&*ptr)).unwrap().0
+            .pad_to_align().unwrap();
 
         let mem = Global.alloc(layout)
             .unwrap_or_else(|_| handle_alloc_error(layout));
 
         // Initialize the RcBox
         let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>;
+        debug_assert_eq!(Layout::for_value(&*inner), layout);
 
         ptr::write(&mut (*inner).strong, Cell::new(1));
         ptr::write(&mut (*inner).weak, Cell::new(1));
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index 2c396b3b06b..b63b3684964 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -575,14 +575,16 @@ impl<T: ?Sized> Arc<T> {
         // 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 layout = Layout::new::<ArcInner<()>>()
+            .extend(Layout::for_value(&*ptr)).unwrap().0
+            .pad_to_align().unwrap();
 
         let mem = Global.alloc(layout)
             .unwrap_or_else(|_| handle_alloc_error(layout));
 
         // Initialize the ArcInner
         let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>;
+        debug_assert_eq!(Layout::for_value(&*inner), layout);
 
         ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1));
         ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));
diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs
index 113a85abecb..dd3e8da18a9 100644
--- a/src/libcore/alloc.rs
+++ b/src/libcore/alloc.rs
@@ -218,6 +218,23 @@ impl Layout {
         len_rounded_up.wrapping_sub(len)
     }
 
+    /// Creates a layout by rounding the size of this layout up to a multiple
+    /// of the layout's alignment.
+    ///
+    /// Returns `Err` if the padded size would overflow.
+    ///
+    /// This is equivalent to adding the result of `padding_needed_for`
+    /// to the layout's current size.
+    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[inline]
+    pub fn pad_to_align(&self) -> Result<Layout, LayoutErr> {
+        let pad = self.padding_needed_for(self.align());
+        let new_size = self.size().checked_add(pad)
+            .ok_or(LayoutErr { private: () })?;
+
+        Layout::from_size_align(new_size, self.align())
+    }
+
     /// Creates a layout describing the record for `n` instances of
     /// `self`, with a suitable amount of padding between each to
     /// ensure that each instance is given its requested size and