@@ -49,7 +49,7 @@ use std::{
49
49
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
50
50
use rustc_index:: vec:: { Idx , IndexVec } ;
51
51
use rustc_middle:: { mir, ty:: layout:: TyAndLayout } ;
52
- use rustc_target:: abi:: Size ;
52
+ use rustc_target:: abi:: { Align , Size } ;
53
53
54
54
use crate :: * ;
55
55
@@ -463,13 +463,30 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
463
463
this. write_scalar_atomic ( value. into ( ) , & value_place, atomic)
464
464
}
465
465
466
+ /// Checks that an atomic access is legal at the given place.
467
+ fn atomic_access_check ( & self , place : & MPlaceTy < ' tcx , Provenance > ) -> InterpResult < ' tcx > {
468
+ let this = self . eval_context_ref ( ) ;
469
+ // Check alignment requirements. Atomics must always be aligned to their size,
470
+ // even if the type they wrap would be less aligned (e.g. AtomicU64 on 32bit must
471
+ // be 8-aligned).
472
+ let align = Align :: from_bytes ( place. layout . size . bytes ( ) ) . unwrap ( ) ;
473
+ this. check_ptr_access_align (
474
+ place. ptr ,
475
+ place. layout . size ,
476
+ align,
477
+ CheckInAllocMsg :: MemoryAccessTest ,
478
+ ) ?;
479
+ Ok ( ( ) )
480
+ }
481
+
466
482
/// Perform an atomic read operation at the memory location.
467
483
fn read_scalar_atomic (
468
484
& self ,
469
485
place : & MPlaceTy < ' tcx , Provenance > ,
470
486
atomic : AtomicReadOrd ,
471
487
) -> InterpResult < ' tcx , ScalarMaybeUninit < Provenance > > {
472
488
let this = self . eval_context_ref ( ) ;
489
+ this. atomic_access_check ( place) ?;
473
490
// This will read from the last store in the modification order of this location. In case
474
491
// weak memory emulation is enabled, this may not be the store we will pick to actually read from and return.
475
492
// This is fine with StackedBorrow and race checks because they don't concern metadata on
@@ -490,6 +507,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
490
507
atomic : AtomicWriteOrd ,
491
508
) -> InterpResult < ' tcx > {
492
509
let this = self . eval_context_mut ( ) ;
510
+ this. atomic_access_check ( dest) ?;
511
+
493
512
this. validate_overlapping_atomic ( dest) ?;
494
513
this. allow_data_races_mut ( move |this| this. write_scalar ( val, & dest. into ( ) ) ) ?;
495
514
this. validate_atomic_store ( dest, atomic) ?;
@@ -511,6 +530,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
511
530
atomic : AtomicRwOrd ,
512
531
) -> InterpResult < ' tcx , ImmTy < ' tcx , Provenance > > {
513
532
let this = self . eval_context_mut ( ) ;
533
+ this. atomic_access_check ( place) ?;
514
534
515
535
this. validate_overlapping_atomic ( place) ?;
516
536
let old = this. allow_data_races_mut ( |this| this. read_immediate ( & place. into ( ) ) ) ?;
@@ -540,6 +560,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
540
560
atomic : AtomicRwOrd ,
541
561
) -> InterpResult < ' tcx , ScalarMaybeUninit < Provenance > > {
542
562
let this = self . eval_context_mut ( ) ;
563
+ this. atomic_access_check ( place) ?;
543
564
544
565
this. validate_overlapping_atomic ( place) ?;
545
566
let old = this. allow_data_races_mut ( |this| this. read_scalar ( & place. into ( ) ) ) ?;
@@ -561,6 +582,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
561
582
atomic : AtomicRwOrd ,
562
583
) -> InterpResult < ' tcx , ImmTy < ' tcx , Provenance > > {
563
584
let this = self . eval_context_mut ( ) ;
585
+ this. atomic_access_check ( place) ?;
564
586
565
587
this. validate_overlapping_atomic ( place) ?;
566
588
let old = this. allow_data_races_mut ( |this| this. read_immediate ( & place. into ( ) ) ) ?;
@@ -604,6 +626,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
604
626
) -> InterpResult < ' tcx , Immediate < Provenance > > {
605
627
use rand:: Rng as _;
606
628
let this = self . eval_context_mut ( ) ;
629
+ this. atomic_access_check ( place) ?;
607
630
608
631
this. validate_overlapping_atomic ( place) ?;
609
632
// Failure ordering cannot be stronger than success ordering, therefore first attempt
@@ -1016,6 +1039,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
1016
1039
fn allow_data_races_ref < R > ( & self , op : impl FnOnce ( & MiriEvalContext < ' mir , ' tcx > ) -> R ) -> R {
1017
1040
let this = self . eval_context_ref ( ) ;
1018
1041
if let Some ( data_race) = & this. machine . data_race {
1042
+ assert ! ( !data_race. ongoing_action_data_race_free. get( ) , "cannot nest allow_data_races" ) ;
1019
1043
data_race. ongoing_action_data_race_free . set ( true ) ;
1020
1044
}
1021
1045
let result = op ( this) ;
@@ -1035,6 +1059,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
1035
1059
) -> R {
1036
1060
let this = self . eval_context_mut ( ) ;
1037
1061
if let Some ( data_race) = & this. machine . data_race {
1062
+ assert ! ( !data_race. ongoing_action_data_race_free. get( ) , "cannot nest allow_data_races" ) ;
1038
1063
data_race. ongoing_action_data_race_free . set ( true ) ;
1039
1064
}
1040
1065
let result = op ( this) ;
0 commit comments