@@ -171,6 +171,7 @@ struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
171
171
path : Vec < PathElem > ,
172
172
ref_tracking_for_consts :
173
173
Option < & ' rt mut RefTracking < MPlaceTy < ' tcx , M :: PointerTag > , Vec < PathElem > > > ,
174
+ may_ref_to_static : bool ,
174
175
ecx : & ' rt InterpCx < ' mir , ' tcx , M > ,
175
176
}
176
177
@@ -324,9 +325,17 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
324
325
self . check_wide_ptr_meta ( place. meta , place. layout ) ?;
325
326
}
326
327
// Make sure this is dereferenceable and all.
327
- let ( size, align) = self
328
- . ecx
329
- . size_and_align_of ( place. meta , place. layout ) ?
328
+ let size_and_align = match self . ecx . size_and_align_of ( place. meta , place. layout ) {
329
+ Ok ( res) => res,
330
+ Err ( err) => match err. kind {
331
+ err_ub ! ( InvalidMeta ( msg) ) => throw_validation_failure ! (
332
+ format_args!( "invalid {} metadata: {}" , kind, msg) ,
333
+ self . path
334
+ ) ,
335
+ _ => bug ! ( "Unexpected error during ptr size_and_align_of: {}" , err) ,
336
+ } ,
337
+ } ;
338
+ let ( size, align) = size_and_align
330
339
// for the purpose of validity, consider foreign types to have
331
340
// alignment and size determined by the layout (size will be 0,
332
341
// alignment should take attributes into account).
@@ -387,6 +396,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
387
396
if !did. is_local ( ) || self . ecx . tcx . is_foreign_item ( did) {
388
397
return Ok ( ( ) ) ;
389
398
}
399
+ if !self . may_ref_to_static && self . ecx . tcx . is_static ( did) {
400
+ throw_validation_failure ! (
401
+ format_args!( "a {} pointing to a static variable" , kind) ,
402
+ self . path
403
+ ) ;
404
+ }
390
405
}
391
406
}
392
407
// Proceed recursively even for ZST, no reason to skip them!
@@ -781,26 +796,20 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
781
796
}
782
797
783
798
impl < ' mir , ' tcx , M : Machine < ' mir , ' tcx > > InterpCx < ' mir , ' tcx , M > {
784
- /// This function checks the data at `op`. `op` is assumed to cover valid memory if it
785
- /// is an indirect operand.
786
- /// It will error if the bits at the destination do not match the ones described by the layout.
787
- ///
788
- /// `ref_tracking_for_consts` can be `None` to avoid recursive checking below references.
789
- /// This also toggles between "run-time" (no recursion) and "compile-time" (with recursion)
790
- /// validation (e.g., pointer values are fine in integers at runtime) and various other const
791
- /// specific validation checks.
792
- pub fn validate_operand (
799
+ fn validate_operand_internal (
793
800
& self ,
794
801
op : OpTy < ' tcx , M :: PointerTag > ,
795
802
path : Vec < PathElem > ,
796
803
ref_tracking_for_consts : Option <
797
804
& mut RefTracking < MPlaceTy < ' tcx , M :: PointerTag > , Vec < PathElem > > ,
798
805
> ,
806
+ may_ref_to_static : bool ,
799
807
) -> InterpResult < ' tcx > {
800
- trace ! ( "validate_operand : {:?}, {:?}" , * op, op. layout. ty) ;
808
+ trace ! ( "validate_operand_internal : {:?}, {:?}" , * op, op. layout. ty) ;
801
809
802
810
// Construct a visitor
803
- let mut visitor = ValidityVisitor { path, ref_tracking_for_consts, ecx : self } ;
811
+ let mut visitor =
812
+ ValidityVisitor { path, ref_tracking_for_consts, may_ref_to_static, ecx : self } ;
804
813
805
814
// Try to cast to ptr *once* instead of all the time.
806
815
let op = self . force_op_ptr ( op) . unwrap_or ( op) ;
@@ -815,4 +824,31 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
815
824
Err ( err) => Err ( err) ,
816
825
}
817
826
}
827
+
828
+ /// This function checks the data at `op` to be const-valid.
829
+ /// `op` is assumed to cover valid memory if it is an indirect operand.
830
+ /// It will error if the bits at the destination do not match the ones described by the layout.
831
+ ///
832
+ /// `ref_tracking` is used to record references that we encounter so that they
833
+ /// can be checked recursively by an outside driving loop.
834
+ ///
835
+ /// `may_ref_to_static` controls whether references are allowed to point to statics.
836
+ #[ inline( always) ]
837
+ pub fn const_validate_operand (
838
+ & self ,
839
+ op : OpTy < ' tcx , M :: PointerTag > ,
840
+ path : Vec < PathElem > ,
841
+ ref_tracking : & mut RefTracking < MPlaceTy < ' tcx , M :: PointerTag > , Vec < PathElem > > ,
842
+ may_ref_to_static : bool ,
843
+ ) -> InterpResult < ' tcx > {
844
+ self . validate_operand_internal ( op, path, Some ( ref_tracking) , may_ref_to_static)
845
+ }
846
+
847
+ /// This function checks the data at `op` to be runtime-valid.
848
+ /// `op` is assumed to cover valid memory if it is an indirect operand.
849
+ /// It will error if the bits at the destination do not match the ones described by the layout.
850
+ #[ inline( always) ]
851
+ pub fn validate_operand ( & self , op : OpTy < ' tcx , M :: PointerTag > ) -> InterpResult < ' tcx > {
852
+ self . validate_operand_internal ( op, vec ! [ ] , None , false )
853
+ }
818
854
}
0 commit comments