@@ -171,6 +171,7 @@ struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
171171 path : Vec < PathElem > ,
172172 ref_tracking_for_consts :
173173 Option < & ' rt mut RefTracking < MPlaceTy < ' tcx , M :: PointerTag > , Vec < PathElem > > > ,
174+ may_ref_to_static : bool ,
174175 ecx : & ' rt InterpCx < ' mir , ' tcx , M > ,
175176}
176177
@@ -324,9 +325,17 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
324325 self . check_wide_ptr_meta ( place. meta , place. layout ) ?;
325326 }
326327 // 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
330339 // for the purpose of validity, consider foreign types to have
331340 // alignment and size determined by the layout (size will be 0,
332341 // alignment should take attributes into account).
@@ -387,6 +396,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
387396 if !did. is_local ( ) || self . ecx . tcx . is_foreign_item ( did) {
388397 return Ok ( ( ) ) ;
389398 }
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+ }
390405 }
391406 }
392407 // 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>
781796}
782797
783798impl < ' 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 (
793800 & self ,
794801 op : OpTy < ' tcx , M :: PointerTag > ,
795802 path : Vec < PathElem > ,
796803 ref_tracking_for_consts : Option <
797804 & mut RefTracking < MPlaceTy < ' tcx , M :: PointerTag > , Vec < PathElem > > ,
798805 > ,
806+ may_ref_to_static : bool ,
799807 ) -> InterpResult < ' tcx > {
800- trace ! ( "validate_operand : {:?}, {:?}" , * op, op. layout. ty) ;
808+ trace ! ( "validate_operand_internal : {:?}, {:?}" , * op, op. layout. ty) ;
801809
802810 // 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 } ;
804813
805814 // Try to cast to ptr *once* instead of all the time.
806815 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> {
815824 Err ( err) => Err ( err) ,
816825 }
817826 }
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+ }
818854}
0 commit comments