diff options
| author | bors <bors@rust-lang.org> | 2020-07-02 12:35:08 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-07-02 12:35:08 +0000 |
| commit | 8a6d4342be6a6acbade8e7ef65e73d27ee8c9144 (patch) | |
| tree | bdb127fa9e94e052cdae4c50e5212d8080863342 /src/libcore/alloc | |
| parent | b7856f695d65a8ebc846754f97d15814bcb1c244 (diff) | |
| parent | 4f536f2c36622328e7eb1d859cb74ba0a7d34ac8 (diff) | |
| download | rust-8a6d4342be6a6acbade8e7ef65e73d27ee8c9144.tar.gz rust-8a6d4342be6a6acbade8e7ef65e73d27ee8c9144.zip | |
Auto merge of #73954 - Manishearth:rollup-8qvh170, r=Manishearth
Rollup of 10 pull requests Successful merges: - #73414 (Implement `slice_strip` feature) - #73564 (linker: Create GNU_EH_FRAME header by default when producing ELFs) - #73622 (Deny unsafe ops in unsafe fns in libcore) - #73684 (add spans to injected coverage counters, extract with CoverageData query) - #73812 (ast_pretty: Pass some token streams and trees by reference) - #73853 (Add newline to rustc MultiSpan docs) - #73883 (Compile rustdoc less often.) - #73885 (Fix wasm32 being broken due to a NodeJS version bump) - #73903 (Changes required for rustc/cargo to build for iOS targets) - #73938 (Optimise fast path of checked_ops with `unlikely`) Failed merges: r? @ghost
Diffstat (limited to 'src/libcore/alloc')
| -rw-r--r-- | src/libcore/alloc/global.rs | 22 | ||||
| -rw-r--r-- | src/libcore/alloc/layout.rs | 3 | ||||
| -rw-r--r-- | src/libcore/alloc/mod.rs | 58 |
3 files changed, 63 insertions, 20 deletions
diff --git a/src/libcore/alloc/global.rs b/src/libcore/alloc/global.rs index 147fe696ac0..c198797e650 100644 --- a/src/libcore/alloc/global.rs +++ b/src/libcore/alloc/global.rs @@ -127,9 +127,12 @@ pub unsafe trait GlobalAlloc { #[stable(feature = "global_alloc", since = "1.28.0")] unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { let size = layout.size(); - let ptr = self.alloc(layout); + // SAFETY: the safety contract for `alloc` must be upheld by the caller. + let ptr = unsafe { self.alloc(layout) }; if !ptr.is_null() { - ptr::write_bytes(ptr, 0, size); + // SAFETY: as allocation succeeded, the region from `ptr` + // of size `size` is guaranteed to be valid for writes. + unsafe { ptr::write_bytes(ptr, 0, size) }; } ptr } @@ -187,11 +190,18 @@ pub unsafe trait GlobalAlloc { /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html #[stable(feature = "global_alloc", since = "1.28.0")] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); - let new_ptr = self.alloc(new_layout); + // SAFETY: the caller must ensure that the `new_size` does not overflow. + // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid. + let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; + // SAFETY: the caller must ensure that `new_layout` is greater than zero. + let new_ptr = unsafe { self.alloc(new_layout) }; if !new_ptr.is_null() { - ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(layout.size(), new_size)); - self.dealloc(ptr, layout); + // SAFETY: the previously allocated block cannot overlap the newly allocated block. + // The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(layout.size(), new_size)); + self.dealloc(ptr, layout); + } } new_ptr } diff --git a/src/libcore/alloc/layout.rs b/src/libcore/alloc/layout.rs index a09c2387d0d..ae7ae704465 100644 --- a/src/libcore/alloc/layout.rs +++ b/src/libcore/alloc/layout.rs @@ -90,7 +90,8 @@ impl Layout { #[rustc_const_stable(feature = "alloc_layout", since = "1.28.0")] #[inline] pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { - Layout { size_: size, align_: NonZeroUsize::new_unchecked(align) } + // SAFETY: the caller must ensure that `align` is greater than zero. + Layout { size_: size, align_: unsafe { NonZeroUsize::new_unchecked(align) } } } /// The minimum size in bytes for a memory block of this layout. diff --git a/src/libcore/alloc/mod.rs b/src/libcore/alloc/mod.rs index 1346fbd4810..be4e051b1ca 100644 --- a/src/libcore/alloc/mod.rs +++ b/src/libcore/alloc/mod.rs @@ -54,7 +54,9 @@ impl AllocInit { #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn init(self, memory: MemoryBlock) { - self.init_offset(memory, 0) + // SAFETY: the safety contract for `init_offset` must be + // upheld by the caller. + unsafe { self.init_offset(memory, 0) } } /// Initialize the memory block like specified by `init` at the specified `offset`. @@ -78,7 +80,10 @@ impl AllocInit { match self { AllocInit::Uninitialized => (), AllocInit::Zeroed => { - memory.ptr.as_ptr().add(offset).write_bytes(0, memory.size - offset) + // SAFETY: the caller must guarantee that `offset` is smaller than or equal to `memory.size`, + // so the memory from `memory.ptr + offset` of length `memory.size - offset` + // is guaranteed to be contaned in `memory` and thus valid for writes. + unsafe { memory.ptr.as_ptr().add(offset).write_bytes(0, memory.size - offset) } } } } @@ -281,11 +286,23 @@ pub unsafe trait AllocRef { return Ok(MemoryBlock { ptr, size }); } - let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); + let new_layout = + // SAFETY: the caller must ensure that the `new_size` does not overflow. + // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout. + // The caller must ensure that `new_size` is greater than zero. + unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; let new_memory = self.alloc(new_layout, init)?; - ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), size); - self.dealloc(ptr, layout); - Ok(new_memory) + + // SAFETY: because `new_size` must be greater than or equal to `size`, both the old and new + // memory allocation are valid for reads and writes for `size` bytes. Also, because the old + // allocation wasn't yet deallocated, it cannot overlap `new_memory`. Thus, the call to + // `copy_nonoverlapping` is safe. + // The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), size); + self.dealloc(ptr, layout); + Ok(new_memory) + } } } } @@ -356,11 +373,23 @@ pub unsafe trait AllocRef { return Ok(MemoryBlock { ptr, size }); } - let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); + let new_layout = + // SAFETY: the caller must ensure that the `new_size` does not overflow. + // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout. + // The caller must ensure that `new_size` is greater than zero. + unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; let new_memory = self.alloc(new_layout, AllocInit::Uninitialized)?; - ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), new_size); - self.dealloc(ptr, layout); - Ok(new_memory) + + // SAFETY: because `new_size` must be lower than or equal to `size`, both the old and new + // memory allocation are valid for reads and writes for `new_size` bytes. Also, because the + // old allocation wasn't yet deallocated, it cannot overlap `new_memory`. Thus, the call to + // `copy_nonoverlapping` is safe. + // The safety contract for `dealloc` must be upheld by the caller. + unsafe { + ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), new_size); + self.dealloc(ptr, layout); + Ok(new_memory) + } } } } @@ -386,7 +415,8 @@ where #[inline] unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) { - (**self).dealloc(ptr, layout) + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).dealloc(ptr, layout) } } #[inline] @@ -398,7 +428,8 @@ where placement: ReallocPlacement, init: AllocInit, ) -> Result<MemoryBlock, AllocErr> { - (**self).grow(ptr, layout, new_size, placement, init) + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).grow(ptr, layout, new_size, placement, init) } } #[inline] @@ -409,6 +440,7 @@ where new_size: usize, placement: ReallocPlacement, ) -> Result<MemoryBlock, AllocErr> { - (**self).shrink(ptr, layout, new_size, placement) + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).shrink(ptr, layout, new_size, placement) } } } |
