77use std:: borrow:: Cow ;
88use std:: fmt:: Write ;
99use std:: hash:: Hash ;
10+ use std:: mem;
1011use std:: num:: NonZero ;
1112
1213use either:: { Left , Right } ;
@@ -288,6 +289,7 @@ struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
288289 /// If this is `Some`, then `reset_provenance_and_padding` must be true (but not vice versa:
289290 /// we might not track data vs padding bytes if the operand isn't stored in memory anyway).
290291 data_bytes : Option < RangeSet > ,
292+ may_dangle : bool ,
291293}
292294
293295impl < ' rt , ' tcx , M : Machine < ' tcx > > ValidityVisitor < ' rt , ' tcx , M > {
@@ -503,27 +505,29 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
503505 // alignment and size determined by the layout (size will be 0,
504506 // alignment should take attributes into account).
505507 . unwrap_or_else ( || ( place. layout . size , place. layout . align . abi ) ) ;
506- // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines.
507- try_validation ! (
508- self . ecx. check_ptr_access(
509- place. ptr( ) ,
510- size,
511- CheckInAllocMsg :: Dereferenceable , // will anyway be replaced by validity message
512- ) ,
513- self . path,
514- Ub ( DanglingIntPointer { addr: 0 , .. } ) => NullPtr { ptr_kind, maybe: false } ,
515- Ub ( DanglingIntPointer { addr: i, .. } ) => DanglingPtrNoProvenance {
516- ptr_kind,
517- // FIXME this says "null pointer" when null but we need translate
518- pointer: format!( "{}" , Pointer :: <Option <AllocId >>:: without_provenance( i) )
519- } ,
520- Ub ( PointerOutOfBounds { .. } ) => DanglingPtrOutOfBounds {
521- ptr_kind
522- } ,
523- Ub ( PointerUseAfterFree ( ..) ) => DanglingPtrUseAfterFree {
524- ptr_kind,
525- } ,
526- ) ;
508+ if !self . may_dangle {
509+ // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines.
510+ try_validation ! (
511+ self . ecx. check_ptr_access(
512+ place. ptr( ) ,
513+ size,
514+ CheckInAllocMsg :: Dereferenceable , // will anyway be replaced by validity message
515+ ) ,
516+ self . path,
517+ Ub ( DanglingIntPointer { addr: 0 , .. } ) => NullPtr { ptr_kind, maybe: false } ,
518+ Ub ( DanglingIntPointer { addr: i, .. } ) => DanglingPtrNoProvenance {
519+ ptr_kind,
520+ // FIXME this says "null pointer" when null but we need translate
521+ pointer: format!( "{}" , Pointer :: <Option <AllocId >>:: without_provenance( i) )
522+ } ,
523+ Ub ( PointerOutOfBounds { .. } ) => DanglingPtrOutOfBounds {
524+ ptr_kind
525+ } ,
526+ Ub ( PointerUseAfterFree ( ..) ) => DanglingPtrUseAfterFree {
527+ ptr_kind,
528+ } ,
529+ ) ;
530+ }
527531 try_validation ! (
528532 self . ecx. check_ptr_align(
529533 place. ptr( ) ,
@@ -536,6 +540,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
536540 found_bytes: has. bytes( )
537541 } ,
538542 ) ;
543+
539544 // Make sure this is non-null. We checked dereferenceability above, but if `size` is zero
540545 // that does not imply non-null.
541546 let scalar = Scalar :: from_maybe_pointer ( place. ptr ( ) , self . ecx ) ;
@@ -1269,6 +1274,14 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
12691274 ty:: PatternKind :: Or ( _patterns) => { }
12701275 }
12711276 }
1277+ ty:: Adt ( adt, _) if adt. is_maybe_dangling ( ) => {
1278+ let could_dangle = mem:: replace ( & mut self . may_dangle , true ) ;
1279+
1280+ let inner = self . ecx . project_field ( val, FieldIdx :: ZERO ) ?;
1281+ self . visit_value ( & inner) ?;
1282+
1283+ self . may_dangle = could_dangle;
1284+ }
12721285 _ => {
12731286 // default handler
12741287 try_validation ! (
@@ -1354,6 +1367,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
13541367 ecx,
13551368 reset_provenance_and_padding,
13561369 data_bytes : reset_padding. then_some ( RangeSet ( Vec :: new ( ) ) ) ,
1370+ may_dangle : false ,
13571371 } ;
13581372 v. visit_value ( val) ?;
13591373 v. reset_padding ( val) ?;
0 commit comments