Skip to content

Commit c38230e

Browse files
committed
Deny unsafe op in unsafe functions in libstd/alloc.rs
1 parent c724b67 commit c38230e

File tree

1 file changed

+71
-20
lines changed

1 file changed

+71
-20
lines changed

src/libstd/alloc.rs

+71-20
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
//! The `#[global_allocator]` can only be used once in a crate
6060
//! or its recursive dependencies.
6161
62+
#![deny(unsafe_op_in_unsafe_fn)]
6263
#![stable(feature = "alloc_module", since = "1.28.0")]
6364

6465
use core::intrinsics;
@@ -158,7 +159,9 @@ unsafe impl AllocRef for System {
158159
#[inline]
159160
unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
160161
if layout.size() != 0 {
161-
GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
162+
// SAFETY: The safety guarantees are explained in the documentation
163+
// for the `GlobalAlloc` trait and its `dealloc` method.
164+
unsafe { GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) }
162165
}
163166
}
164167

@@ -184,16 +187,36 @@ unsafe impl AllocRef for System {
184187
match placement {
185188
ReallocPlacement::InPlace => Err(AllocErr),
186189
ReallocPlacement::MayMove if layout.size() == 0 => {
187-
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
190+
let new_layout =
191+
// SAFETY: The new size and layout alignement guarantees
192+
// are transfered to the caller (they come from parameters).
193+
//
194+
// See the preconditions for `Layout::from_size_align` to
195+
// see what must be checked.
196+
unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) };
188197
self.alloc(new_layout, init)
189198
}
190199
ReallocPlacement::MayMove => {
191-
// `realloc` probably checks for `new_size > size` or something similar.
192-
intrinsics::assume(new_size > size);
193-
let ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size);
194-
let memory =
195-
MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size };
196-
init.init_offset(memory, size);
200+
// SAFETY:
201+
//
202+
// The safety guarantees are explained in the documentation
203+
// for the `GlobalAlloc` trait and its `dealloc` method.
204+
//
205+
// `realloc` probably checks for `new_size > size` or something
206+
// similar.
207+
//
208+
// For the guarantees about `init_offset`, see its documentation:
209+
// `ptr` is assumed valid (and checked for non-NUL) and
210+
// `memory.size` is set to `new_size` so the offset being `size`
211+
// is valid.
212+
let memory = unsafe {
213+
intrinsics::assume(new_size > size);
214+
let ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size);
215+
let memory =
216+
MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size };
217+
init.init_offset(memory, size);
218+
memory
219+
};
197220
Ok(memory)
198221
}
199222
}
@@ -220,14 +243,28 @@ unsafe impl AllocRef for System {
220243
match placement {
221244
ReallocPlacement::InPlace => Err(AllocErr),
222245
ReallocPlacement::MayMove if new_size == 0 => {
223-
self.dealloc(ptr, layout);
246+
// SAFETY: see `GlobalAlloc::dealloc` for the guarantees that
247+
// must be respected. `ptr` and `layout` are parameters and so
248+
// those guarantees must be checked by the caller.
249+
unsafe { self.dealloc(ptr, layout) };
224250
Ok(MemoryBlock { ptr: layout.dangling(), size: 0 })
225251
}
226252
ReallocPlacement::MayMove => {
227-
// `realloc` probably checks for `new_size < size` or something similar.
228-
intrinsics::assume(new_size < size);
229-
let ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size);
230-
Ok(MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size })
253+
// SAFETY:
254+
//
255+
// See `GlobalAlloc::realloc` for more informations about the
256+
// guarantees expected by this method. `ptr`, `layout` and
257+
// `new_size` are parameters and the responsability for their
258+
// correctness is left to the caller.
259+
//
260+
// `realloc` probably checks for `new_size < size` or something
261+
// similar.
262+
let memory = unsafe {
263+
intrinsics::assume(new_size < size);
264+
let ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size);
265+
MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size }
266+
};
267+
Ok(memory)
231268
}
232269
}
233270
}
@@ -300,13 +337,19 @@ pub mod __default_lib_allocator {
300337

301338
#[rustc_std_internal_symbol]
302339
pub unsafe extern "C" fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
303-
let layout = Layout::from_size_align_unchecked(size, align);
304-
System.alloc(layout)
340+
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
341+
// `GlobalAlloc::alloc`.
342+
unsafe {
343+
let layout = Layout::from_size_align_unchecked(size, align);
344+
System.alloc(layout)
345+
}
305346
}
306347

307348
#[rustc_std_internal_symbol]
308349
pub unsafe extern "C" fn __rdl_dealloc(ptr: *mut u8, size: usize, align: usize) {
309-
System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
350+
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
351+
// `GlobalAlloc::dealloc`.
352+
unsafe { System.dealloc(ptr, Layout::from_size_align_unchecked(size, align)) }
310353
}
311354

312355
#[rustc_std_internal_symbol]
@@ -316,13 +359,21 @@ pub mod __default_lib_allocator {
316359
align: usize,
317360
new_size: usize,
318361
) -> *mut u8 {
319-
let old_layout = Layout::from_size_align_unchecked(old_size, align);
320-
System.realloc(ptr, old_layout, new_size)
362+
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
363+
// `GlobalAlloc::realloc`.
364+
unsafe {
365+
let old_layout = Layout::from_size_align_unchecked(old_size, align);
366+
System.realloc(ptr, old_layout, new_size)
367+
}
321368
}
322369

323370
#[rustc_std_internal_symbol]
324371
pub unsafe extern "C" fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
325-
let layout = Layout::from_size_align_unchecked(size, align);
326-
System.alloc_zeroed(layout)
372+
// SAFETY: see the guarantees expected by `Layout::from_size_align` and
373+
// `GlobalAlloc::alloc_zeroed`.
374+
unsafe {
375+
let layout = Layout::from_size_align_unchecked(size, align);
376+
System.alloc_zeroed(layout)
377+
}
327378
}
328379
}

0 commit comments

Comments
 (0)