@@ -258,14 +258,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
258
258
None => self . get_alloc_raw ( alloc_id) ?. size ( ) ,
259
259
} ;
260
260
// This will also call the access hooks.
261
- self . mem_copy (
262
- ptr,
263
- Align :: ONE ,
264
- new_ptr. into ( ) ,
265
- Align :: ONE ,
266
- old_size. min ( new_size) ,
267
- /*nonoverlapping*/ true ,
268
- ) ?;
261
+ self . mem_copy ( ptr, new_ptr. into ( ) , old_size. min ( new_size) , /*nonoverlapping*/ true ) ?;
269
262
self . deallocate_ptr ( ptr, old_size_and_align, kind) ?;
270
263
271
264
Ok ( new_ptr)
@@ -367,12 +360,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
367
360
& self ,
368
361
ptr : Pointer < Option < M :: Provenance > > ,
369
362
size : Size ,
370
- align : Align ,
371
363
) -> InterpResult < ' tcx , Option < ( AllocId , Size , M :: ProvenanceExtra ) > > {
372
364
self . check_and_deref_ptr (
373
365
ptr,
374
366
size,
375
- align,
376
367
CheckInAllocMsg :: MemoryAccessTest ,
377
368
|alloc_id, offset, prov| {
378
369
let ( size, align) = self
@@ -382,17 +373,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
382
373
)
383
374
}
384
375
385
- /// Check if the given pointer points to live memory of given `size` and `align `.
376
+ /// Check if the given pointer points to live memory of the given `size`.
386
377
/// The caller can control the error message for the out-of-bounds case.
387
378
#[ inline( always) ]
388
- pub fn check_ptr_access_align (
379
+ pub fn check_ptr_access (
389
380
& self ,
390
381
ptr : Pointer < Option < M :: Provenance > > ,
391
382
size : Size ,
392
- align : Align ,
393
383
msg : CheckInAllocMsg ,
394
384
) -> InterpResult < ' tcx > {
395
- self . check_and_deref_ptr ( ptr, size, align , msg, |alloc_id, _, _| {
385
+ self . check_and_deref_ptr ( ptr, size, msg, |alloc_id, _, _| {
396
386
let ( size, align) = self . get_live_alloc_size_and_align ( alloc_id, msg) ?;
397
387
Ok ( ( size, align, ( ) ) )
398
388
} ) ?;
@@ -408,7 +398,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
408
398
& self ,
409
399
ptr : Pointer < Option < M :: Provenance > > ,
410
400
size : Size ,
411
- align : Align ,
412
401
msg : CheckInAllocMsg ,
413
402
alloc_size : impl FnOnce (
414
403
AllocId ,
@@ -423,17 +412,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
423
412
if size. bytes ( ) > 0 || addr == 0 {
424
413
throw_ub ! ( DanglingIntPointer ( addr, msg) ) ;
425
414
}
426
- // Must be aligned.
427
- if M :: enforce_alignment ( self ) && align. bytes ( ) > 1 {
428
- self . check_misalign (
429
- Self :: offset_misalignment ( addr, align) ,
430
- CheckAlignMsg :: AccessedPtr ,
431
- ) ?;
432
- }
433
415
None
434
416
}
435
417
Ok ( ( alloc_id, offset, prov) ) => {
436
- let ( alloc_size, alloc_align , ret_val) = alloc_size ( alloc_id, offset, prov) ?;
418
+ let ( alloc_size, _alloc_align , ret_val) = alloc_size ( alloc_id, offset, prov) ?;
437
419
// Test bounds. This also ensures non-null.
438
420
// It is sufficient to check this for the end pointer. Also check for overflow!
439
421
if offset. checked_add ( size, & self . tcx ) . map_or ( true , |end| end > alloc_size) {
@@ -449,14 +431,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
449
431
if M :: Provenance :: OFFSET_IS_ADDR {
450
432
assert_ne ! ( ptr. addr( ) , Size :: ZERO ) ;
451
433
}
452
- // Test align. Check this last; if both bounds and alignment are violated
453
- // we want the error to be about the bounds.
454
- if M :: enforce_alignment ( self ) && align. bytes ( ) > 1 {
455
- self . check_misalign (
456
- self . alloc_misalignment ( ptr, offset, align, alloc_align) ,
457
- CheckAlignMsg :: AccessedPtr ,
458
- ) ?;
459
- }
460
434
461
435
// We can still be zero-sized in this branch, in which case we have to
462
436
// return `None`.
@@ -465,7 +439,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
465
439
} )
466
440
}
467
441
468
- #[ inline( always) ]
469
442
pub ( super ) fn check_misalign (
470
443
& self ,
471
444
misaligned : Option < Misalignment > ,
@@ -477,54 +450,55 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
477
450
Ok ( ( ) )
478
451
}
479
452
480
- #[ must_use]
481
- fn offset_misalignment ( offset : u64 , align : Align ) -> Option < Misalignment > {
482
- if offset % align. bytes ( ) == 0 {
483
- None
484
- } else {
485
- // The biggest power of two through which `offset` is divisible.
486
- let offset_pow2 = 1 << offset. trailing_zeros ( ) ;
487
- Some ( Misalignment { has : Align :: from_bytes ( offset_pow2) . unwrap ( ) , required : align } )
488
- }
489
- }
490
-
491
- #[ must_use]
492
- fn alloc_misalignment (
453
+ pub ( super ) fn is_ptr_misaligned (
493
454
& self ,
494
455
ptr : Pointer < Option < M :: Provenance > > ,
495
- offset : Size ,
496
456
align : Align ,
497
- alloc_align : Align ,
498
457
) -> Option < Misalignment > {
499
- if M :: use_addr_for_alignment_check ( self ) {
500
- // `use_addr_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true.
501
- Self :: offset_misalignment ( ptr. addr ( ) . bytes ( ) , align)
502
- } else {
503
- // Check allocation alignment and offset alignment.
504
- if alloc_align. bytes ( ) < align. bytes ( ) {
505
- Some ( Misalignment { has : alloc_align, required : align } )
458
+ if !M :: enforce_alignment ( self ) || align. bytes ( ) == 1 {
459
+ return None ;
460
+ }
461
+
462
+ #[ inline]
463
+ fn offset_misalignment ( offset : u64 , align : Align ) -> Option < Misalignment > {
464
+ if offset % align. bytes ( ) == 0 {
465
+ None
506
466
} else {
507
- Self :: offset_misalignment ( offset. bytes ( ) , align)
467
+ // The biggest power of two through which `offset` is divisible.
468
+ let offset_pow2 = 1 << offset. trailing_zeros ( ) ;
469
+ Some ( Misalignment { has : Align :: from_bytes ( offset_pow2) . unwrap ( ) , required : align } )
508
470
}
509
471
}
510
- }
511
472
512
- pub ( super ) fn is_ptr_misaligned (
513
- & self ,
514
- ptr : Pointer < Option < M :: Provenance > > ,
515
- align : Align ,
516
- ) -> Option < Misalignment > {
517
- if !M :: enforce_alignment ( self ) {
518
- return None ;
519
- }
520
473
match self . ptr_try_get_alloc_id ( ptr) {
521
- Err ( addr) => Self :: offset_misalignment ( addr, align) ,
474
+ Err ( addr) => offset_misalignment ( addr, align) ,
522
475
Ok ( ( alloc_id, offset, _prov) ) => {
523
476
let ( _size, alloc_align, _kind) = self . get_alloc_info ( alloc_id) ;
524
- self . alloc_misalignment ( ptr, offset, align, alloc_align)
477
+ if M :: use_addr_for_alignment_check ( self ) {
478
+ // `use_addr_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true.
479
+ offset_misalignment ( ptr. addr ( ) . bytes ( ) , align)
480
+ } else {
481
+ // Check allocation alignment and offset alignment.
482
+ if alloc_align. bytes ( ) < align. bytes ( ) {
483
+ Some ( Misalignment { has : alloc_align, required : align } )
484
+ } else {
485
+ offset_misalignment ( offset. bytes ( ) , align)
486
+ }
487
+ }
525
488
}
526
489
}
527
490
}
491
+
492
+ /// Checks a pointer for misalignment.
493
+ ///
494
+ /// The error assumes this is checking the pointer used directly for an access.
495
+ pub fn check_ptr_align (
496
+ & self ,
497
+ ptr : Pointer < Option < M :: Provenance > > ,
498
+ align : Align ,
499
+ ) -> InterpResult < ' tcx > {
500
+ self . check_misalign ( self . is_ptr_misaligned ( ptr, align) , CheckAlignMsg :: AccessedPtr )
501
+ }
528
502
}
529
503
530
504
/// Allocation accessors
@@ -629,18 +603,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
629
603
}
630
604
}
631
605
632
- /// "Safe" (bounds and align-checked) allocation access.
606
+ /// Bounds-checked *but not align-checked* allocation access.
633
607
pub fn get_ptr_alloc < ' a > (
634
608
& ' a self ,
635
609
ptr : Pointer < Option < M :: Provenance > > ,
636
610
size : Size ,
637
- align : Align ,
638
611
) -> InterpResult < ' tcx , Option < AllocRef < ' a , ' tcx , M :: Provenance , M :: AllocExtra , M :: Bytes > > >
639
612
{
640
613
let ptr_and_alloc = self . check_and_deref_ptr (
641
614
ptr,
642
615
size,
643
- align,
644
616
CheckInAllocMsg :: MemoryAccessTest ,
645
617
|alloc_id, offset, prov| {
646
618
let alloc = self . get_alloc_raw ( alloc_id) ?;
@@ -701,15 +673,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
701
673
Ok ( ( alloc, & mut self . machine ) )
702
674
}
703
675
704
- /// "Safe" (bounds and align-checked) allocation access.
676
+ /// Bounds-checked *but not align-checked* allocation access.
705
677
pub fn get_ptr_alloc_mut < ' a > (
706
678
& ' a mut self ,
707
679
ptr : Pointer < Option < M :: Provenance > > ,
708
680
size : Size ,
709
- align : Align ,
710
681
) -> InterpResult < ' tcx , Option < AllocRefMut < ' a , ' tcx , M :: Provenance , M :: AllocExtra , M :: Bytes > > >
711
682
{
712
- let parts = self . get_ptr_access ( ptr, size, align ) ?;
683
+ let parts = self . get_ptr_access ( ptr, size) ?;
713
684
if let Some ( ( alloc_id, offset, prov) ) = parts {
714
685
let tcx = * self . tcx ;
715
686
// FIXME: can we somehow avoid looking up the allocation twice here?
@@ -1066,7 +1037,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
1066
1037
ptr : Pointer < Option < M :: Provenance > > ,
1067
1038
size : Size ,
1068
1039
) -> InterpResult < ' tcx , & [ u8 ] > {
1069
- let Some ( alloc_ref) = self . get_ptr_alloc ( ptr, size, Align :: ONE ) ? else {
1040
+ let Some ( alloc_ref) = self . get_ptr_alloc ( ptr, size) ? else {
1070
1041
// zero-sized access
1071
1042
return Ok ( & [ ] ) ;
1072
1043
} ;
@@ -1092,7 +1063,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
1092
1063
assert_eq ! ( lower, len, "can only write iterators with a precise length" ) ;
1093
1064
1094
1065
let size = Size :: from_bytes ( len) ;
1095
- let Some ( alloc_ref) = self . get_ptr_alloc_mut ( ptr, size, Align :: ONE ) ? else {
1066
+ let Some ( alloc_ref) = self . get_ptr_alloc_mut ( ptr, size) ? else {
1096
1067
// zero-sized access
1097
1068
assert_matches ! ( src. next( ) , None , "iterator said it was empty but returned an element" ) ;
1098
1069
return Ok ( ( ) ) ;
@@ -1117,29 +1088,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
1117
1088
pub fn mem_copy (
1118
1089
& mut self ,
1119
1090
src : Pointer < Option < M :: Provenance > > ,
1120
- src_align : Align ,
1121
1091
dest : Pointer < Option < M :: Provenance > > ,
1122
- dest_align : Align ,
1123
1092
size : Size ,
1124
1093
nonoverlapping : bool ,
1125
1094
) -> InterpResult < ' tcx > {
1126
- self . mem_copy_repeatedly ( src, src_align , dest, dest_align , size, 1 , nonoverlapping)
1095
+ self . mem_copy_repeatedly ( src, dest, size, 1 , nonoverlapping)
1127
1096
}
1128
1097
1129
1098
pub fn mem_copy_repeatedly (
1130
1099
& mut self ,
1131
1100
src : Pointer < Option < M :: Provenance > > ,
1132
- src_align : Align ,
1133
1101
dest : Pointer < Option < M :: Provenance > > ,
1134
- dest_align : Align ,
1135
1102
size : Size ,
1136
1103
num_copies : u64 ,
1137
1104
nonoverlapping : bool ,
1138
1105
) -> InterpResult < ' tcx > {
1139
1106
let tcx = self . tcx ;
1140
1107
// We need to do our own bounds-checks.
1141
- let src_parts = self . get_ptr_access ( src, size, src_align ) ?;
1142
- let dest_parts = self . get_ptr_access ( dest, size * num_copies, dest_align ) ?; // `Size` multiplication
1108
+ let src_parts = self . get_ptr_access ( src, size) ?;
1109
+ let dest_parts = self . get_ptr_access ( dest, size * num_copies) ?; // `Size` multiplication
1143
1110
1144
1111
// FIXME: we look up both allocations twice here, once before for the `check_ptr_access`
1145
1112
// and once below to get the underlying `&[mut] Allocation`.
0 commit comments