7
7
//! short-circuiting the empty case!
8
8
9
9
use std:: assert_matches:: assert_matches;
10
- use std:: borrow:: Cow ;
10
+ use std:: borrow:: { Borrow , Cow } ;
11
11
use std:: collections:: VecDeque ;
12
12
use std:: { fmt, mem, ptr} ;
13
13
@@ -386,12 +386,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
386
386
size : Size ,
387
387
) -> InterpResult < ' tcx , Option < ( AllocId , Size , M :: ProvenanceExtra ) > > {
388
388
let size = i64:: try_from ( size. bytes ( ) ) . unwrap ( ) ; // it would be an error to even ask for more than isize::MAX bytes
389
- self . check_and_deref_ptr (
389
+ Self :: check_and_deref_ptr (
390
+ self ,
390
391
ptr,
391
392
size,
392
393
CheckInAllocMsg :: MemoryAccessTest ,
393
- |alloc_id, offset, prov| {
394
- let ( size, align) = self
394
+ |this , alloc_id, offset, prov| {
395
+ let ( size, align) = this
395
396
. get_live_alloc_size_and_align ( alloc_id, CheckInAllocMsg :: MemoryAccessTest ) ?;
396
397
Ok ( ( size, align, ( alloc_id, offset, prov) ) )
397
398
} ,
@@ -408,8 +409,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
408
409
msg : CheckInAllocMsg ,
409
410
) -> InterpResult < ' tcx > {
410
411
let size = i64:: try_from ( size. bytes ( ) ) . unwrap ( ) ; // it would be an error to even ask for more than isize::MAX bytes
411
- self . check_and_deref_ptr ( ptr, size, msg, |alloc_id, _, _| {
412
- let ( size, align) = self . get_live_alloc_size_and_align ( alloc_id, msg) ?;
412
+ Self :: check_and_deref_ptr ( self , ptr, size, msg, |this , alloc_id, _, _| {
413
+ let ( size, align) = this . get_live_alloc_size_and_align ( alloc_id, msg) ?;
413
414
Ok ( ( size, align, ( ) ) )
414
415
} ) ?;
415
416
Ok ( ( ) )
@@ -424,8 +425,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
424
425
size : i64 ,
425
426
msg : CheckInAllocMsg ,
426
427
) -> InterpResult < ' tcx > {
427
- self . check_and_deref_ptr ( ptr, size, msg, |alloc_id, _, _| {
428
- let ( size, align) = self . get_live_alloc_size_and_align ( alloc_id, msg) ?;
428
+ Self :: check_and_deref_ptr ( self , ptr, size, msg, |this , alloc_id, _, _| {
429
+ let ( size, align) = this . get_live_alloc_size_and_align ( alloc_id, msg) ?;
429
430
Ok ( ( size, align, ( ) ) )
430
431
} ) ?;
431
432
Ok ( ( ) )
@@ -439,12 +440,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
439
440
/// `alloc_size` will only get called for non-zero-sized accesses.
440
441
///
441
442
/// Returns `None` if and only if the size is 0.
442
- fn check_and_deref_ptr < T > (
443
- & self ,
443
+ fn check_and_deref_ptr < T , R : Borrow < Self > > (
444
+ this : R ,
444
445
ptr : Pointer < Option < M :: Provenance > > ,
445
446
size : i64 ,
446
447
msg : CheckInAllocMsg ,
447
448
alloc_size : impl FnOnce (
449
+ R ,
448
450
AllocId ,
449
451
Size ,
450
452
M :: ProvenanceExtra ,
@@ -455,13 +457,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
455
457
return Ok ( None ) ;
456
458
}
457
459
458
- Ok ( match self . ptr_try_get_alloc_id ( ptr, size) {
460
+ Ok ( match this . borrow ( ) . ptr_try_get_alloc_id ( ptr, size) {
459
461
Err ( addr) => {
460
462
// We couldn't get a proper allocation.
461
463
throw_ub ! ( DanglingIntPointer { addr, inbounds_size: size, msg } ) ;
462
464
}
463
465
Ok ( ( alloc_id, offset, prov) ) => {
464
- let ( alloc_size, _alloc_align, ret_val) = alloc_size ( alloc_id, offset, prov) ?;
466
+ let tcx = this. borrow ( ) . tcx ;
467
+ let ( alloc_size, _alloc_align, ret_val) = alloc_size ( this, alloc_id, offset, prov) ?;
465
468
let offset = offset. bytes ( ) ;
466
469
// Compute absolute begin and end of the range.
467
470
let ( begin, end) = if size >= 0 {
@@ -475,7 +478,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
475
478
throw_ub ! ( PointerOutOfBounds {
476
479
alloc_id,
477
480
alloc_size,
478
- ptr_offset: self . sign_extend_to_target_isize( offset) ,
481
+ ptr_offset: tcx . sign_extend_to_target_isize( offset) ,
479
482
inbounds_size: size,
480
483
msg,
481
484
} )
@@ -669,12 +672,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
669
672
) -> InterpResult < ' tcx , Option < AllocRef < ' a , ' tcx , M :: Provenance , M :: AllocExtra , M :: Bytes > > >
670
673
{
671
674
let size_i64 = i64:: try_from ( size. bytes ( ) ) . unwrap ( ) ; // it would be an error to even ask for more than isize::MAX bytes
672
- let ptr_and_alloc = self . check_and_deref_ptr (
675
+ let ptr_and_alloc = Self :: check_and_deref_ptr (
676
+ self ,
673
677
ptr,
674
678
size_i64,
675
679
CheckInAllocMsg :: MemoryAccessTest ,
676
- |alloc_id, offset, prov| {
677
- let alloc = self . get_alloc_raw ( alloc_id) ?;
680
+ |this , alloc_id, offset, prov| {
681
+ let alloc = this . get_alloc_raw ( alloc_id) ?;
678
682
Ok ( ( alloc. size ( ) , alloc. align , ( alloc_id, offset, prov, alloc) ) )
679
683
} ,
680
684
) ?;
@@ -726,7 +730,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
726
730
// We have "NLL problem case #3" here, which cannot be worked around without loss of
727
731
// efficiency even for the common case where the key is in the map.
728
732
// <https://rust-lang.github.io/rfcs/2094-nll.html#problem-case-3-conditional-control-flow-across-functions>
729
- // (Cannot use `get_mut_or` since `get_global_alloc` needs `&self`.)
733
+ // (Cannot use `get_mut_or` since `get_global_alloc` needs `&self`, and that boils down to
734
+ // Miri's `adjust_alloc_root_pointer` needing to look up the size of the allocation.
735
+ // It could be avoided with a totally separate codepath in Miri for handling the absolute address
736
+ // of global allocations, but that's not worth it.)
730
737
if self . memory . alloc_map . get_mut ( id) . is_none ( ) {
731
738
// Slow path.
732
739
// Allocation not found locally, go look global.
@@ -762,13 +769,22 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
762
769
size : Size ,
763
770
) -> InterpResult < ' tcx , Option < AllocRefMut < ' a , ' tcx , M :: Provenance , M :: AllocExtra , M :: Bytes > > >
764
771
{
765
- let parts = self . get_ptr_access ( ptr, size) ?;
766
- if let Some ( ( alloc_id, offset, prov) ) = parts {
767
- let tcx = self . tcx ;
768
- let validation_in_progress = self . memory . validation_in_progress ;
769
- // FIXME: can we somehow avoid looking up the allocation twice here?
770
- // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`.
771
- let ( alloc, machine) = self . get_alloc_raw_mut ( alloc_id) ?;
772
+ let tcx = self . tcx ;
773
+ let validation_in_progress = self . memory . validation_in_progress ;
774
+
775
+ let size_i64 = i64:: try_from ( size. bytes ( ) ) . unwrap ( ) ; // it would be an error to even ask for more than isize::MAX bytes
776
+ let ptr_and_alloc = Self :: check_and_deref_ptr (
777
+ self ,
778
+ ptr,
779
+ size_i64,
780
+ CheckInAllocMsg :: MemoryAccessTest ,
781
+ |this, alloc_id, offset, prov| {
782
+ let ( alloc, machine) = this. get_alloc_raw_mut ( alloc_id) ?;
783
+ Ok ( ( alloc. size ( ) , alloc. align , ( alloc_id, offset, prov, alloc, machine) ) )
784
+ } ,
785
+ ) ?;
786
+
787
+ if let Some ( ( alloc_id, offset, prov, alloc, machine) ) = ptr_and_alloc {
772
788
let range = alloc_range ( offset, size) ;
773
789
if !validation_in_progress {
774
790
M :: before_memory_write ( tcx, machine, & mut alloc. extra , ( alloc_id, prov) , range) ?;
0 commit comments