diff options
| author | Tim Diekmann <tim.diekmann@3dvision.de> | 2020-03-26 17:11:47 +0100 |
|---|---|---|
| committer | Tim Diekmann <tim.diekmann@3dvision.de> | 2020-03-26 17:11:47 +0100 |
| commit | 2526accdd35c564eee80b6453a0b4965e6a76afd (patch) | |
| tree | 76705d1a424dc9682b2e1c2599db6a0985d25335 /src/liballoc/alloc.rs | |
| parent | 56cbf2f22aeb6448acd7eb49e9b2554c80bdbf79 (diff) | |
| download | rust-2526accdd35c564eee80b6453a0b4965e6a76afd.tar.gz rust-2526accdd35c564eee80b6453a0b4965e6a76afd.zip | |
Fix issues from review and unsoundness of `RawVec::into_box`
Diffstat (limited to 'src/liballoc/alloc.rs')
| -rw-r--r-- | src/liballoc/alloc.rs | 96 |
1 files changed, 45 insertions, 51 deletions
diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index 26524f62962..7eb9e0d5ea3 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -4,7 +4,7 @@ use core::intrinsics::{self, min_align_of_val, size_of_val}; use core::ptr::{NonNull, Unique}; -use core::usize; +use core::{mem, usize}; #[stable(feature = "alloc_module", since = "1.28.0")] #[doc(inline)] @@ -165,102 +165,96 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl AllocRef for Global { #[inline] - fn alloc(&mut self, layout: Layout, init: AllocInit) -> Result<(NonNull<u8>, usize), AllocErr> { - let new_size = layout.size(); - if new_size == 0 { - Ok((layout.dangling(), 0)) - } else { - unsafe { + fn alloc(&mut self, layout: Layout, init: AllocInit) -> Result<MemoryBlock, AllocErr> { + unsafe { + if layout.size() == 0 { + Ok(MemoryBlock::new(layout.dangling(), layout)) + } else { let raw_ptr = match init { AllocInit::Uninitialized => alloc(layout), AllocInit::Zeroed => alloc_zeroed(layout), }; let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?; - Ok((ptr, new_size)) + Ok(MemoryBlock::new(ptr, layout)) } } } #[inline] - unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) { - if layout.size() != 0 { - dealloc(ptr.as_ptr(), layout) + unsafe fn dealloc(&mut self, memory: MemoryBlock) { + if memory.size() != 0 { + dealloc(memory.ptr().as_ptr(), memory.layout()) } } #[inline] unsafe fn grow( &mut self, - ptr: NonNull<u8>, - layout: Layout, + memory: &mut MemoryBlock, new_size: usize, placement: ReallocPlacement, init: AllocInit, - ) -> Result<(NonNull<u8>, usize), AllocErr> { - let old_size = layout.size(); + ) -> Result<(), AllocErr> { + let old_size = memory.size(); debug_assert!( new_size >= old_size, - "`new_size` must be greater than or equal to `layout.size()`" + "`new_size` must be greater than or equal to `memory.size()`" ); if old_size == new_size { - return Ok((ptr, new_size)); + return Ok(()); } + let new_layout = Layout::from_size_align_unchecked(new_size, memory.align()); match placement { + ReallocPlacement::InPlace => return Err(AllocErr), + ReallocPlacement::MayMove if memory.size() == 0 => { + *memory = self.alloc(new_layout, init)? + } ReallocPlacement::MayMove => { - if old_size == 0 { - self.alloc(Layout::from_size_align_unchecked(new_size, layout.align()), init) - } else { - // `realloc` probably checks for `new_size > old_size` or something similar. - // `new_size` must be greater than or equal to `old_size` due to the safety constraint, - // and `new_size` == `old_size` was caught before - intrinsics::assume(new_size > old_size); - let ptr = - NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)?; - let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); - init.initialize_offset(ptr, new_layout, old_size); - Ok((ptr, new_size)) - } + // `realloc` probably checks for `new_size > old_size` or something similar. + intrinsics::assume(new_size > old_size); + let ptr = realloc(memory.ptr().as_ptr(), memory.layout(), new_size); + *memory = MemoryBlock::new(NonNull::new(ptr).ok_or(AllocErr)?, new_layout); + memory.init_offset(init, old_size); } - ReallocPlacement::InPlace => Err(AllocErr), } + Ok(()) } #[inline] unsafe fn shrink( &mut self, - ptr: NonNull<u8>, - layout: Layout, + memory: &mut MemoryBlock, new_size: usize, placement: ReallocPlacement, - ) -> Result<(NonNull<u8>, usize), AllocErr> { - let old_size = layout.size(); + ) -> Result<(), AllocErr> { + let old_size = memory.size(); debug_assert!( new_size <= old_size, - "`new_size` must be smaller than or equal to `layout.size()`" + "`new_size` must be smaller than or equal to `memory.size()`" ); if old_size == new_size { - return Ok((ptr, new_size)); + return Ok(()); } + let new_layout = Layout::from_size_align_unchecked(new_size, memory.align()); match placement { + ReallocPlacement::InPlace => return Err(AllocErr), + ReallocPlacement::MayMove if new_size == 0 => { + let new_memory = MemoryBlock::new(new_layout.dangling(), new_layout); + let old_memory = mem::replace(memory, new_memory); + self.dealloc(old_memory) + } ReallocPlacement::MayMove => { - let ptr = if new_size == 0 { - self.dealloc(ptr, layout); - layout.dangling() - } else { - // `realloc` probably checks for `new_size > old_size` or something similar. - // `new_size` must be smaller than or equal to `old_size` due to the safety constraint, - // and `new_size` == `old_size` was caught before - intrinsics::assume(new_size < old_size); - NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)? - }; - Ok((ptr, new_size)) + // `realloc` probably checks for `new_size < old_size` or something similar. + intrinsics::assume(new_size < old_size); + let ptr = realloc(memory.ptr().as_ptr(), memory.layout(), new_size); + *memory = MemoryBlock::new(NonNull::new(ptr).ok_or(AllocErr)?, new_layout); } - ReallocPlacement::InPlace => Err(AllocErr), } + Ok(()) } } @@ -272,7 +266,7 @@ unsafe impl AllocRef for Global { unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { let layout = Layout::from_size_align_unchecked(size, align); match Global.alloc(layout, AllocInit::Uninitialized) { - Ok((ptr, _)) => ptr.as_ptr(), + Ok(memory) => memory.ptr().as_ptr(), Err(_) => handle_alloc_error(layout), } } @@ -288,7 +282,7 @@ pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) { let size = size_of_val(ptr.as_ref()); let align = min_align_of_val(ptr.as_ref()); let layout = Layout::from_size_align_unchecked(size, align); - Global.dealloc(ptr.cast().into(), layout) + Global.dealloc(MemoryBlock::new(ptr.cast().into(), layout)) } /// Abort on memory allocation error or failure. |
