11//! Memory allocation APIs
22
33#![ stable( feature = "alloc_module" , since = "1.28.0" ) ]
4+ #![ deny( unsafe_op_in_unsafe_fn) ]
45
56mod global;
67mod layout;
@@ -54,7 +55,9 @@ impl AllocInit {
5455 #[ inline]
5556 #[ unstable( feature = "allocator_api" , issue = "32838" ) ]
5657 pub unsafe fn init ( self , memory : MemoryBlock ) {
57- self . init_offset ( memory, 0 )
58+ // SAFETY: the safety contract for `init_offset` must be
59+ // upheld by the caller.
60+ unsafe { self . init_offset ( memory, 0 ) }
5861 }
5962
6063 /// Initialize the memory block like specified by `init` at the specified `offset`.
@@ -78,7 +81,10 @@ impl AllocInit {
7881 match self {
7982 AllocInit :: Uninitialized => ( ) ,
8083 AllocInit :: Zeroed => {
81- memory. ptr . as_ptr ( ) . add ( offset) . write_bytes ( 0 , memory. size - offset)
84+ // SAFETY: the caller must guarantee that `offset` is smaller than or equal to `memory.size`,
85+ // so the memory from `memory.ptr + offset` of length `memory.size - offset`
86+ // is guaranteed to be contaned in `memory` and thus valid for writes.
87+ unsafe { memory. ptr . as_ptr ( ) . add ( offset) . write_bytes ( 0 , memory. size - offset) }
8288 }
8389 }
8490 }
@@ -281,11 +287,23 @@ pub unsafe trait AllocRef {
281287 return Ok ( MemoryBlock { ptr, size } ) ;
282288 }
283289
284- let new_layout = Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ;
290+ let new_layout =
291+ // SAFETY: the caller must ensure that the `new_size` does not overflow.
292+ // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
293+ // The caller must ensure that `new_size` is greater than zero.
294+ unsafe { Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) } ;
285295 let new_memory = self . alloc ( new_layout, init) ?;
286- ptr:: copy_nonoverlapping ( ptr. as_ptr ( ) , new_memory. ptr . as_ptr ( ) , size) ;
287- self . dealloc ( ptr, layout) ;
288- Ok ( new_memory)
296+
297+ // SAFETY: because `new_size` must be greater than or equal to `size`, both the old and new
298+ // memory allocation are valid for reads and writes for `size` bytes. Also, because the old
299+ // allocation wasn't yet deallocated, it cannot overlap `new_memory`. Thus, the call to
300+ // `copy_nonoverlapping` is safe.
301+ // The safety contract for `dealloc` must be upheld by the caller.
302+ unsafe {
303+ ptr:: copy_nonoverlapping ( ptr. as_ptr ( ) , new_memory. ptr . as_ptr ( ) , size) ;
304+ self . dealloc ( ptr, layout) ;
305+ Ok ( new_memory)
306+ }
289307 }
290308 }
291309 }
@@ -356,11 +374,23 @@ pub unsafe trait AllocRef {
356374 return Ok ( MemoryBlock { ptr, size } ) ;
357375 }
358376
359- let new_layout = Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ;
377+ let new_layout =
378+ // SAFETY: the caller must ensure that the `new_size` does not overflow.
379+ // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
380+ // The caller must ensure that `new_size` is greater than zero.
381+ unsafe { Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) } ;
360382 let new_memory = self . alloc ( new_layout, AllocInit :: Uninitialized ) ?;
361- ptr:: copy_nonoverlapping ( ptr. as_ptr ( ) , new_memory. ptr . as_ptr ( ) , new_size) ;
362- self . dealloc ( ptr, layout) ;
363- Ok ( new_memory)
383+
384+ // SAFETY: because `new_size` must be lower than or equal to `size`, both the old and new
385+ // memory allocation are valid for reads and writes for `new_size` bytes. Also, because the
386+ // old allocation wasn't yet deallocated, it cannot overlap `new_memory`. Thus, the call to
387+ // `copy_nonoverlapping` is safe.
388+ // The safety contract for `dealloc` must be upheld by the caller.
389+ unsafe {
390+ ptr:: copy_nonoverlapping ( ptr. as_ptr ( ) , new_memory. ptr . as_ptr ( ) , new_size) ;
391+ self . dealloc ( ptr, layout) ;
392+ Ok ( new_memory)
393+ }
364394 }
365395 }
366396 }
@@ -386,7 +416,8 @@ where
386416
387417 #[ inline]
388418 unsafe fn dealloc ( & mut self , ptr : NonNull < u8 > , layout : Layout ) {
389- ( * * self ) . dealloc ( ptr, layout)
419+ // SAFETY: the safety contract must be upheld by the caller
420+ unsafe { ( * * self ) . dealloc ( ptr, layout) }
390421 }
391422
392423 #[ inline]
@@ -398,7 +429,8 @@ where
398429 placement : ReallocPlacement ,
399430 init : AllocInit ,
400431 ) -> Result < MemoryBlock , AllocErr > {
401- ( * * self ) . grow ( ptr, layout, new_size, placement, init)
432+ // SAFETY: the safety contract must be upheld by the caller
433+ unsafe { ( * * self ) . grow ( ptr, layout, new_size, placement, init) }
402434 }
403435
404436 #[ inline]
@@ -409,6 +441,7 @@ where
409441 new_size : usize ,
410442 placement : ReallocPlacement ,
411443 ) -> Result < MemoryBlock , AllocErr > {
412- ( * * self ) . shrink ( ptr, layout, new_size, placement)
444+ // SAFETY: the safety contract must be upheld by the caller
445+ unsafe { ( * * self ) . shrink ( ptr, layout, new_size, placement) }
413446 }
414447}
0 commit comments