@@ -54,7 +54,9 @@ impl AllocInit {
54
54
#[ inline]
55
55
#[ unstable( feature = "allocator_api" , issue = "32838" ) ]
56
56
pub unsafe fn init ( self , memory : MemoryBlock ) {
57
- self . init_offset ( memory, 0 )
57
+ // SAFETY: the safety contract for `init_offset` must be
58
+ // upheld by the caller.
59
+ unsafe { self . init_offset ( memory, 0 ) }
58
60
}
59
61
60
62
/// Initialize the memory block like specified by `init` at the specified `offset`.
@@ -78,7 +80,10 @@ impl AllocInit {
78
80
match self {
79
81
AllocInit :: Uninitialized => ( ) ,
80
82
AllocInit :: Zeroed => {
81
- memory. ptr . as_ptr ( ) . add ( offset) . write_bytes ( 0 , memory. size - offset)
83
+ // SAFETY: the caller must guarantee that `offset` is smaller than or equal to `memory.size`,
84
+ // so the memory from `memory.ptr + offset` of length `memory.size - offset`
85
+ // is guaranteed to be contaned in `memory` and thus valid for writes.
86
+ unsafe { memory. ptr . as_ptr ( ) . add ( offset) . write_bytes ( 0 , memory. size - offset) }
82
87
}
83
88
}
84
89
}
@@ -281,11 +286,23 @@ pub unsafe trait AllocRef {
281
286
return Ok ( MemoryBlock { ptr, size } ) ;
282
287
}
283
288
284
- let new_layout = Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ;
289
+ let new_layout =
290
+ // SAFETY: the caller must ensure that the `new_size` does not overflow.
291
+ // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
292
+ // The caller must ensure that `new_size` is greater than zero.
293
+ unsafe { Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) } ;
285
294
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)
295
+
296
+ // SAFETY: because `new_size` must be greater than or equal to `size`, both the old and new
297
+ // memory allocation are valid for reads and writes for `size` bytes. Also, because the old
298
+ // allocation wasn't yet deallocated, it cannot overlap `new_memory`. Thus, the call to
299
+ // `copy_nonoverlapping` is safe.
300
+ // The safety contract for `dealloc` must be upheld by the caller.
301
+ unsafe {
302
+ ptr:: copy_nonoverlapping ( ptr. as_ptr ( ) , new_memory. ptr . as_ptr ( ) , size) ;
303
+ self . dealloc ( ptr, layout) ;
304
+ Ok ( new_memory)
305
+ }
289
306
}
290
307
}
291
308
}
@@ -356,11 +373,23 @@ pub unsafe trait AllocRef {
356
373
return Ok ( MemoryBlock { ptr, size } ) ;
357
374
}
358
375
359
- let new_layout = Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ;
376
+ let new_layout =
377
+ // SAFETY: the caller must ensure that the `new_size` does not overflow.
378
+ // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid for a Layout.
379
+ // The caller must ensure that `new_size` is greater than zero.
380
+ unsafe { Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) } ;
360
381
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)
382
+
383
+ // SAFETY: because `new_size` must be lower than or equal to `size`, both the old and new
384
+ // memory allocation are valid for reads and writes for `new_size` bytes. Also, because the
385
+ // old allocation wasn't yet deallocated, it cannot overlap `new_memory`. Thus, the call to
386
+ // `copy_nonoverlapping` is safe.
387
+ // The safety contract for `dealloc` must be upheld by the caller.
388
+ unsafe {
389
+ ptr:: copy_nonoverlapping ( ptr. as_ptr ( ) , new_memory. ptr . as_ptr ( ) , new_size) ;
390
+ self . dealloc ( ptr, layout) ;
391
+ Ok ( new_memory)
392
+ }
364
393
}
365
394
}
366
395
}
@@ -386,7 +415,8 @@ where
386
415
387
416
#[ inline]
388
417
unsafe fn dealloc ( & mut self , ptr : NonNull < u8 > , layout : Layout ) {
389
- ( * * self ) . dealloc ( ptr, layout)
418
+ // SAFETY: the safety contract must be upheld by the caller
419
+ unsafe { ( * * self ) . dealloc ( ptr, layout) }
390
420
}
391
421
392
422
#[ inline]
@@ -398,7 +428,8 @@ where
398
428
placement : ReallocPlacement ,
399
429
init : AllocInit ,
400
430
) -> Result < MemoryBlock , AllocErr > {
401
- ( * * self ) . grow ( ptr, layout, new_size, placement, init)
431
+ // SAFETY: the safety contract must be upheld by the caller
432
+ unsafe { ( * * self ) . grow ( ptr, layout, new_size, placement, init) }
402
433
}
403
434
404
435
#[ inline]
@@ -409,6 +440,7 @@ where
409
440
new_size : usize ,
410
441
placement : ReallocPlacement ,
411
442
) -> Result < MemoryBlock , AllocErr > {
412
- ( * * self ) . shrink ( ptr, layout, new_size, placement)
443
+ // SAFETY: the safety contract must be upheld by the caller
444
+ unsafe { ( * * self ) . shrink ( ptr, layout, new_size, placement) }
413
445
}
414
446
}
0 commit comments