@@ -215,7 +215,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
215
215
kind : MemoryKind < M :: MemoryKinds > ,
216
216
) -> InterpResult < ' tcx , Pointer < M :: PointerTag > > {
217
217
if ptr. offset . bytes ( ) != 0 {
218
- throw_unsup ! ( ReallocateNonBasePtr )
218
+ throw_ub_format ! (
219
+ "reallocating {:?} which does not point to the beginning of an object" ,
220
+ ptr
221
+ ) ;
219
222
}
220
223
221
224
// For simplicities' sake, we implement reallocate as "alloc, copy, dealloc".
@@ -251,37 +254,43 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
251
254
trace ! ( "deallocating: {}" , ptr. alloc_id) ;
252
255
253
256
if ptr. offset . bytes ( ) != 0 {
254
- throw_unsup ! ( DeallocateNonBasePtr )
257
+ throw_ub_format ! (
258
+ "deallocating {:?} which does not point to the beginning of an object" ,
259
+ ptr
260
+ ) ;
255
261
}
256
262
257
263
let ( alloc_kind, mut alloc) = match self . alloc_map . remove ( & ptr. alloc_id ) {
258
264
Some ( alloc) => alloc,
259
265
None => {
260
266
// Deallocating static memory -- always an error
261
267
return Err ( match self . tcx . alloc_map . lock ( ) . get ( ptr. alloc_id ) {
262
- Some ( GlobalAlloc :: Function ( ..) ) => err_unsup ! ( DeallocatedWrongMemoryKind (
263
- "function" . to_string( ) ,
264
- format!( "{:?}" , kind) ,
265
- ) ) ,
266
- Some ( GlobalAlloc :: Static ( ..) ) | Some ( GlobalAlloc :: Memory ( ..) ) => err_unsup ! (
267
- DeallocatedWrongMemoryKind ( "static" . to_string( ) , format!( "{:?}" , kind) )
268
- ) ,
269
- None => err_unsup ! ( DoubleFree ) ,
268
+ Some ( GlobalAlloc :: Function ( ..) ) => err_ub_format ! ( "deallocating a function" ) ,
269
+ Some ( GlobalAlloc :: Static ( ..) ) | Some ( GlobalAlloc :: Memory ( ..) ) => {
270
+ err_ub_format ! ( "deallocating static memory" )
271
+ }
272
+ None => err_ub ! ( PointerUseAfterFree ( ptr. alloc_id) ) ,
270
273
}
271
274
. into ( ) ) ;
272
275
}
273
276
} ;
274
277
275
278
if alloc_kind != kind {
276
- throw_unsup ! ( DeallocatedWrongMemoryKind (
277
- format!( "{:?}" , alloc_kind) ,
278
- format!( "{:?}" , kind) ,
279
- ) )
279
+ throw_ub_format ! (
280
+ "deallocating `{:?}` memory using `{:?}` deallocation operation" ,
281
+ alloc_kind,
282
+ kind
283
+ ) ;
280
284
}
281
285
if let Some ( ( size, align) ) = old_size_and_align {
282
286
if size != alloc. size || align != alloc. align {
283
- let bytes = alloc. size ;
284
- throw_unsup ! ( IncorrectAllocationInformation ( size, bytes, align, alloc. align) )
287
+ throw_ub_format ! (
288
+ "incorrect layout on deallocation: allocation has size {} and alignment {}, but gave size {} and alignment {}" ,
289
+ alloc. size. bytes( ) ,
290
+ alloc. align. bytes( ) ,
291
+ size. bytes( ) ,
292
+ align. bytes( ) ,
293
+ )
285
294
}
286
295
}
287
296
@@ -338,7 +347,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
338
347
} else {
339
348
// The biggest power of two through which `offset` is divisible.
340
349
let offset_pow2 = 1 << offset. trailing_zeros ( ) ;
341
- throw_unsup ! ( AlignmentCheckFailed {
350
+ throw_ub ! ( AlignmentCheckFailed {
342
351
has: Align :: from_bytes( offset_pow2) . unwrap( ) ,
343
352
required: align,
344
353
} )
@@ -360,7 +369,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
360
369
assert ! ( size. bytes( ) == 0 ) ;
361
370
// Must be non-NULL.
362
371
if bits == 0 {
363
- throw_unsup ! ( InvalidNullPointerUsage )
372
+ throw_ub ! ( InvalidIntPointerUsage ( 0 ) )
364
373
}
365
374
// Must be aligned.
366
375
if let Some ( align) = align {
@@ -375,7 +384,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
375
384
// It is sufficient to check this for the end pointer. The addition
376
385
// checks for overflow.
377
386
let end_ptr = ptr. offset ( size, self ) ?;
378
- end_ptr. check_inbounds_alloc ( allocation_size, msg) ?;
387
+ if end_ptr. offset > allocation_size {
388
+ // equal is okay!
389
+ throw_ub ! ( PointerOutOfBounds { ptr: end_ptr. erase_tag( ) , msg, allocation_size } )
390
+ }
379
391
// Test align. Check this last; if both bounds and alignment are violated
380
392
// we want the error to be about the bounds.
381
393
if let Some ( align) = align {
@@ -385,7 +397,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
385
397
// got picked we might be aligned even if this check fails.
386
398
// We instead have to fall back to converting to an integer and checking
387
399
// the "real" alignment.
388
- throw_unsup ! ( AlignmentCheckFailed { has: alloc_align, required: align } ) ;
400
+ throw_ub ! ( AlignmentCheckFailed { has: alloc_align, required: align } ) ;
389
401
}
390
402
check_offset_align ( ptr. offset . bytes ( ) , align) ?;
391
403
}
@@ -402,7 +414,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
402
414
let ( size, _align) = self
403
415
. get_size_and_align ( ptr. alloc_id , AllocCheck :: MaybeDead )
404
416
. expect ( "alloc info with MaybeDead cannot fail" ) ;
405
- ptr. check_inbounds_alloc ( size, CheckInAllocMsg :: NullPointerTest ) . is_err ( )
417
+ // If the pointer is out-of-bounds, it may be null.
418
+ // Note that one-past-the-end (offset == size) is still inbounds, and never null.
419
+ ptr. offset > size
406
420
}
407
421
}
408
422
@@ -432,13 +446,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
432
446
let alloc = tcx. alloc_map . lock ( ) . get ( id) ;
433
447
let alloc = match alloc {
434
448
Some ( GlobalAlloc :: Memory ( mem) ) => Cow :: Borrowed ( mem) ,
435
- Some ( GlobalAlloc :: Function ( ..) ) => throw_unsup ! ( DerefFunctionPointer ) ,
436
- None => throw_unsup ! ( DanglingPointerDeref ) ,
449
+ Some ( GlobalAlloc :: Function ( ..) ) => throw_ub ! ( DerefFunctionPointer ( id ) ) ,
450
+ None => throw_ub ! ( PointerUseAfterFree ( id ) ) ,
437
451
Some ( GlobalAlloc :: Static ( def_id) ) => {
438
452
// We got a "lazy" static that has not been computed yet.
439
453
if tcx. is_foreign_item ( def_id) {
440
454
trace ! ( "get_static_alloc: foreign item {:?}" , def_id) ;
441
- throw_unsup ! ( ReadForeignStatic )
455
+ throw_unsup ! ( ReadForeignStatic ( def_id ) )
442
456
}
443
457
trace ! ( "get_static_alloc: Need to compute {:?}" , def_id) ;
444
458
let instance = Instance :: mono ( tcx. tcx , def_id) ;
@@ -524,7 +538,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
524
538
// to give us a cheap reference.
525
539
let alloc = Self :: get_static_alloc ( memory_extra, tcx, id) ?;
526
540
if alloc. mutability == Mutability :: Not {
527
- throw_unsup ! ( ModifiedConstantMemory )
541
+ throw_ub ! ( WriteToReadOnly ( id ) )
528
542
}
529
543
match M :: STATIC_KIND {
530
544
Some ( kind) => Ok ( ( MemoryKind :: Machine ( kind) , alloc. into_owned ( ) ) ) ,
@@ -538,7 +552,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
538
552
Ok ( a) => {
539
553
let a = & mut a. 1 ;
540
554
if a. mutability == Mutability :: Not {
541
- throw_unsup ! ( ModifiedConstantMemory )
555
+ throw_ub ! ( WriteToReadOnly ( id ) )
542
556
}
543
557
Ok ( a)
544
558
}
@@ -568,7 +582,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
568
582
if self . get_fn_alloc ( id) . is_some ( ) {
569
583
return if let AllocCheck :: Dereferenceable = liveness {
570
584
// The caller requested no function pointers.
571
- throw_unsup ! ( DerefFunctionPointer )
585
+ throw_ub ! ( DerefFunctionPointer ( id ) )
572
586
} else {
573
587
Ok ( ( Size :: ZERO , Align :: from_bytes ( 1 ) . unwrap ( ) ) )
574
588
} ;
@@ -596,12 +610,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
596
610
if let AllocCheck :: MaybeDead = liveness {
597
611
// Deallocated pointers are allowed, we should be able to find
598
612
// them in the map.
599
- Ok ( * self . dead_alloc_map . get ( & id ) . expect (
600
- "deallocated pointers should all be recorded in \
601
- `dead_alloc_map`" ,
602
- ) )
613
+ Ok ( * self
614
+ . dead_alloc_map
615
+ . get ( & id )
616
+ . expect ( "deallocated pointers should all be recorded in `dead_alloc_map`" ) )
603
617
} else {
604
- throw_unsup ! ( DanglingPointerDeref )
618
+ throw_ub ! ( PointerUseAfterFree ( id ) )
605
619
}
606
620
}
607
621
}
@@ -626,10 +640,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
626
640
) -> InterpResult < ' tcx , FnVal < ' tcx , M :: ExtraFnVal > > {
627
641
let ptr = self . force_ptr ( ptr) ?; // We definitely need a pointer value.
628
642
if ptr. offset . bytes ( ) != 0 {
629
- throw_unsup ! ( InvalidFunctionPointer )
643
+ throw_ub ! ( InvalidFunctionPointer ( ptr . erase_tag ( ) ) )
630
644
}
631
645
let id = M :: canonical_alloc_id ( self , ptr. alloc_id ) ;
632
- self . get_fn_alloc ( id) . ok_or_else ( || err_unsup ! ( ExecuteMemory ) . into ( ) )
646
+ self . get_fn_alloc ( id) . ok_or_else ( || err_ub ! ( InvalidFunctionPointer ( ptr . erase_tag ( ) ) ) . into ( ) )
633
647
}
634
648
635
649
pub fn mark_immutable ( & mut self , id : AllocId ) -> InterpResult < ' tcx > {
0 commit comments