59
59
//! The `#[global_allocator]` can only be used once in a crate
60
60
//! or its recursive dependencies.
61
61
62
+ #![ deny( unsafe_op_in_unsafe_fn) ]
62
63
#![ stable( feature = "alloc_module" , since = "1.28.0" ) ]
63
64
64
65
use core:: intrinsics;
@@ -158,7 +159,9 @@ unsafe impl AllocRef for System {
158
159
#[ inline]
159
160
unsafe fn dealloc ( & mut self , ptr : NonNull < u8 > , layout : Layout ) {
160
161
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) }
162
165
}
163
166
}
164
167
@@ -184,16 +187,36 @@ unsafe impl AllocRef for System {
184
187
match placement {
185
188
ReallocPlacement :: InPlace => Err ( AllocErr ) ,
186
189
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 ( ) ) } ;
188
197
self . alloc ( new_layout, init)
189
198
}
190
199
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
+ } ;
197
220
Ok ( memory)
198
221
}
199
222
}
@@ -220,14 +243,28 @@ unsafe impl AllocRef for System {
220
243
match placement {
221
244
ReallocPlacement :: InPlace => Err ( AllocErr ) ,
222
245
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) } ;
224
250
Ok ( MemoryBlock { ptr : layout. dangling ( ) , size : 0 } )
225
251
}
226
252
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)
231
268
}
232
269
}
233
270
}
@@ -300,13 +337,19 @@ pub mod __default_lib_allocator {
300
337
301
338
#[ rustc_std_internal_symbol]
302
339
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
+ }
305
346
}
306
347
307
348
#[ rustc_std_internal_symbol]
308
349
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) ) }
310
353
}
311
354
312
355
#[ rustc_std_internal_symbol]
@@ -316,13 +359,21 @@ pub mod __default_lib_allocator {
316
359
align : usize ,
317
360
new_size : usize ,
318
361
) -> * 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
+ }
321
368
}
322
369
323
370
#[ rustc_std_internal_symbol]
324
371
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
+ }
327
378
}
328
379
}
0 commit comments