@@ -272,7 +272,8 @@ struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
272
272
ctfe_mode : Option < CtfeValidationMode > ,
273
273
ecx : & ' rt mut InterpCx < ' tcx , M > ,
274
274
/// Whether provenance should be reset outside of pointers (emulating the effect of a typed
275
- /// copy).
275
+ /// copy). If this is `true`, then `M::RESET_PROVENANCE_AND_PADDING` is true, but not vice
276
+ /// versa since we don't want to reset adding for recursive validation.
276
277
reset_provenance_and_padding : bool ,
277
278
/// This tracks which byte ranges in this value contain data; the remaining bytes are padding.
278
279
/// The ideal representation here would be pointer-length pairs, but to keep things more compact
@@ -416,7 +417,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
416
417
let imm = self . read_immediate ( val, expected) ?;
417
418
// Reset provenance: ensure slice tail metadata does not preserve provenance,
418
419
// and ensure all pointers do not preserve partial provenance.
419
- if self . reset_provenance_and_padding {
420
+ if self . reset_provenance_and_padding ( ) {
420
421
if matches ! ( imm. layout. abi, Abi :: Scalar ( ..) ) {
421
422
// A thin pointer. If it has provenance, we don't have to do anything.
422
423
// If it does not, ensure we clear the provenance in memory.
@@ -676,7 +677,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
676
677
value: format!( "{scalar:x}" ) ,
677
678
}
678
679
) ;
679
- if self . reset_provenance_and_padding {
680
+ if self . reset_provenance_and_padding ( ) {
680
681
self . ecx . clear_provenance ( value) ?;
681
682
self . add_data_range_place ( value) ;
682
683
}
@@ -691,7 +692,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
691
692
value: format!( "{scalar:x}" ) ,
692
693
}
693
694
) ;
694
- if self . reset_provenance_and_padding {
695
+ if self . reset_provenance_and_padding ( ) {
695
696
self . ecx . clear_provenance ( value) ?;
696
697
self . add_data_range_place ( value) ;
697
698
}
@@ -708,7 +709,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
708
709
ExpectedKind :: Int
709
710
} ,
710
711
) ?;
711
- if self . reset_provenance_and_padding {
712
+ if self . reset_provenance_and_padding ( ) {
712
713
self . ecx . clear_provenance ( value) ?;
713
714
self . add_data_range_place ( value) ;
714
715
}
@@ -744,7 +745,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
744
745
throw_validation_failure ! ( self . path, NullFnPtr ) ;
745
746
}
746
747
}
747
- if self . reset_provenance_and_padding {
748
+ if self . reset_provenance_and_padding ( ) {
748
749
// Make sure we do not preserve partial provenance. This matches the thin
749
750
// pointer handling in `deref_pointer`.
750
751
if matches ! ( scalar, Scalar :: Int ( ..) ) {
@@ -847,6 +848,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
847
848
}
848
849
}
849
850
851
+ #[ inline( always) ]
852
+ fn reset_provenance_and_padding ( & self ) -> bool {
853
+ // Make sure this becomes a constant `false` when `M::RESET_PADDING_AND_PROVENANCE` is `false`.
854
+ // This way, all the padding/provenance reset code paths can be removed in the CTFE machine.
855
+ M :: RESET_PROVENANCE_AND_PADDING && self . reset_provenance_and_padding
856
+ }
857
+
850
858
/// Add the given pointer-length pair to the "data" range of this visit.
851
859
fn add_data_range ( & mut self , ptr : Pointer < Option < M :: Provenance > > , size : Size ) {
852
860
if let Some ( data_bytes) = self . data_bytes . as_mut ( ) {
@@ -882,6 +890,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
882
890
}
883
891
884
892
fn reset_padding ( & mut self , place : & PlaceTy < ' tcx , M :: Provenance > ) -> InterpResult < ' tcx > {
893
+ if !M :: RESET_PROVENANCE_AND_PADDING {
894
+ return Ok ( ( ) ) ;
895
+ }
885
896
let Some ( data_bytes) = self . data_bytes . as_mut ( ) else { return Ok ( ( ) ) } ;
886
897
// Our value must be in memory, otherwise we would not have set up `data_bytes`.
887
898
let mplace = self . ecx . force_allocation ( place) ?;
@@ -1122,7 +1133,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
1122
1133
}
1123
1134
}
1124
1135
}
1125
- if self . reset_provenance_and_padding
1136
+ if self . reset_provenance_and_padding ( )
1126
1137
&& let Some ( data_bytes) = self . data_bytes . as_mut ( )
1127
1138
{
1128
1139
let base_offset = Self :: data_range_offset ( self . ecx , val) ;
@@ -1255,7 +1266,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
1255
1266
1256
1267
// Don't forget that these are all non-pointer types, and thus do not preserve
1257
1268
// provenance.
1258
- if self . reset_provenance_and_padding {
1269
+ if self . reset_provenance_and_padding ( ) {
1259
1270
// We can't share this with above as above, we might be looking at read-only memory.
1260
1271
let mut alloc = self . ecx . get_ptr_alloc_mut ( mplace. ptr ( ) , size) ?. expect ( "we already excluded size 0" ) ;
1261
1272
alloc. clear_provenance ( ) ?;
@@ -1346,6 +1357,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
1346
1357
1347
1358
// Run the visitor.
1348
1359
match self . run_for_validation ( |ecx| {
1360
+ if reset_provenance_and_padding {
1361
+ // Check the invariant relating `reset_provenance_and_padding` to this constant.
1362
+ assert ! ( M :: RESET_PROVENANCE_AND_PADDING ) ;
1363
+ }
1349
1364
let reset_padding = reset_provenance_and_padding && {
1350
1365
// Check if `val` is actually stored in memory. If not, padding is not even
1351
1366
// represented and we need not reset it.
@@ -1409,7 +1424,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
1409
1424
path,
1410
1425
Some ( ref_tracking) ,
1411
1426
Some ( ctfe_mode) ,
1412
- /*reset_provenance */ false ,
1427
+ /*reset_provenance_and_padding */ false ,
1413
1428
)
1414
1429
}
1415
1430
@@ -1421,7 +1436,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
1421
1436
& mut self ,
1422
1437
val : & PlaceTy < ' tcx , M :: Provenance > ,
1423
1438
recursive : bool ,
1424
- reset_provenance_and_padding : bool ,
1425
1439
) -> InterpResult < ' tcx > {
1426
1440
// Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's
1427
1441
// still correct to not use `ctfe_mode`: that mode is for validation of the final constant
@@ -1432,7 +1446,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
1432
1446
vec ! [ ] ,
1433
1447
None ,
1434
1448
None ,
1435
- reset_provenance_and_padding ,
1449
+ M :: RESET_PROVENANCE_AND_PADDING ,
1436
1450
) ;
1437
1451
}
1438
1452
// Do a recursive check.
@@ -1442,7 +1456,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
1442
1456
vec ! [ ] ,
1443
1457
Some ( & mut ref_tracking) ,
1444
1458
None ,
1445
- reset_provenance_and_padding ,
1459
+ M :: RESET_PROVENANCE_AND_PADDING ,
1446
1460
) ?;
1447
1461
while let Some ( ( mplace, path) ) = ref_tracking. todo . pop ( ) {
1448
1462
// Things behind reference do *not* have the provenance reset.
0 commit comments