@@ -7,15 +7,15 @@ use rustc::hir::def::Def;
7
7
use rustc:: hir:: map:: definitions:: DefPathData ;
8
8
use rustc:: mir;
9
9
use rustc:: ty:: layout:: {
10
- self , Size , Align , HasDataLayout , LayoutOf , TyLayout , Primitive
10
+ self , Size , Align , HasDataLayout , LayoutOf , TyLayout
11
11
} ;
12
12
use rustc:: ty:: subst:: { Subst , Substs } ;
13
13
use rustc:: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
14
14
use rustc:: ty:: query:: TyCtxtAt ;
15
15
use rustc_data_structures:: fx:: { FxHashSet , FxHasher } ;
16
16
use rustc_data_structures:: indexed_vec:: IndexVec ;
17
17
use rustc:: mir:: interpret:: {
18
- GlobalId , Scalar , FrameInfo , AllocType ,
18
+ GlobalId , Scalar , FrameInfo ,
19
19
EvalResult , EvalErrorKind ,
20
20
ScalarMaybeUndef ,
21
21
truncate, sign_extend,
@@ -29,31 +29,6 @@ use super::{
29
29
Memory , Machine
30
30
} ;
31
31
32
- macro_rules! validation_failure{
33
- ( $what: expr, $where: expr, $details: expr) => { {
34
- let where_ = if $where. is_empty( ) {
35
- String :: new( )
36
- } else {
37
- format!( " at {}" , $where)
38
- } ;
39
- err!( ValidationFailure ( format!(
40
- "encountered {}{}, but expected {}" ,
41
- $what, where_, $details,
42
- ) ) )
43
- } } ;
44
- ( $what: expr, $where: expr) => { {
45
- let where_ = if $where. is_empty( ) {
46
- String :: new( )
47
- } else {
48
- format!( " at {}" , $where)
49
- } ;
50
- err!( ValidationFailure ( format!(
51
- "encountered {}{}" ,
52
- $what, where_,
53
- ) ) )
54
- } } ;
55
- }
56
-
57
32
pub struct EvalContext < ' a , ' mir , ' tcx : ' a + ' mir , M : Machine < ' mir , ' tcx > > {
58
33
/// Stores the `Machine` instance.
59
34
pub machine : M ,
@@ -670,243 +645,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
670
645
self . tcx . const_eval ( param_env. and ( gid) ) . map_err ( |err| EvalErrorKind :: ReferencedConstant ( err) . into ( ) )
671
646
}
672
647
673
- fn validate_scalar (
674
- & self ,
675
- value : ScalarMaybeUndef ,
676
- size : Size ,
677
- scalar : & layout:: Scalar ,
678
- path : & str ,
679
- ty : Ty ,
680
- ) -> EvalResult < ' tcx > {
681
- trace ! ( "validate scalar: {:#?}, {:#?}, {:#?}, {}" , value, size, scalar, ty) ;
682
- let ( lo, hi) = scalar. valid_range . clone ( ) . into_inner ( ) ;
683
-
684
- let value = match value {
685
- ScalarMaybeUndef :: Scalar ( scalar) => scalar,
686
- ScalarMaybeUndef :: Undef => return validation_failure ! ( "undefined bytes" , path) ,
687
- } ;
688
-
689
- let bits = match value {
690
- Scalar :: Bits { bits, size : value_size } => {
691
- assert_eq ! ( value_size as u64 , size. bytes( ) ) ;
692
- bits
693
- } ,
694
- Scalar :: Ptr ( _) => {
695
- let ptr_size = self . memory . pointer_size ( ) ;
696
- let ptr_max = u128:: max_value ( ) >> ( 128 - ptr_size. bits ( ) ) ;
697
- return if lo > hi {
698
- if lo - hi == 1 {
699
- // no gap, all values are ok
700
- Ok ( ( ) )
701
- } else if hi < ptr_max || lo > 1 {
702
- let max = u128:: max_value ( ) >> ( 128 - size. bits ( ) ) ;
703
- validation_failure ! (
704
- "pointer" ,
705
- path,
706
- format!( "something in the range {:?} or {:?}" , 0 ..=lo, hi..=max)
707
- )
708
- } else {
709
- Ok ( ( ) )
710
- }
711
- } else if hi < ptr_max || lo > 1 {
712
- validation_failure ! (
713
- "pointer" ,
714
- path,
715
- format!( "something in the range {:?}" , scalar. valid_range)
716
- )
717
- } else {
718
- Ok ( ( ) )
719
- } ;
720
- } ,
721
- } ;
722
-
723
- // char gets a special treatment, because its number space is not contiguous so `TyLayout`
724
- // has no special checks for chars
725
- match ty. sty {
726
- ty:: TyChar => {
727
- debug_assert_eq ! ( size. bytes( ) , 4 ) ;
728
- if :: std:: char:: from_u32 ( bits as u32 ) . is_none ( ) {
729
- return err ! ( InvalidChar ( bits) ) ;
730
- }
731
- }
732
- _ => { } ,
733
- }
734
-
735
- use std:: ops:: RangeInclusive ;
736
- let in_range = |bound : RangeInclusive < u128 > | bound. contains ( & bits) ;
737
- if lo > hi {
738
- if in_range ( 0 ..=hi) || in_range ( lo..=u128:: max_value ( ) ) {
739
- Ok ( ( ) )
740
- } else {
741
- validation_failure ! (
742
- bits,
743
- path,
744
- format!( "something in the range {:?} or {:?}" , ..=hi, lo..)
745
- )
746
- }
747
- } else {
748
- if in_range ( scalar. valid_range . clone ( ) ) {
749
- Ok ( ( ) )
750
- } else {
751
- validation_failure ! (
752
- bits,
753
- path,
754
- format!( "something in the range {:?}" , scalar. valid_range)
755
- )
756
- }
757
- }
758
- }
759
-
760
- /// This function checks the memory where `ptr` points to.
761
- /// It will error if the bits at the destination do not match the ones described by the layout.
762
- pub fn validate_mplace (
763
- & self ,
764
- dest : MPlaceTy < ' tcx > ,
765
- path : String ,
766
- seen : & mut FxHashSet < ( MPlaceTy < ' tcx > ) > ,
767
- todo : & mut Vec < ( MPlaceTy < ' tcx > , String ) > ,
768
- ) -> EvalResult < ' tcx > {
769
- self . memory . dump_alloc ( dest. to_ptr ( ) ?. alloc_id ) ;
770
- trace ! ( "validate_mplace: {:?}, {:#?}" , * dest, dest. layout) ;
771
-
772
- // Find the right variant
773
- let ( variant, dest) = match dest. layout . variants {
774
- layout:: Variants :: NicheFilling { niche : ref tag, .. } |
775
- layout:: Variants :: Tagged { ref tag, .. } => {
776
- let size = tag. value . size ( self ) ;
777
- // we first read the tag value as scalar, to be able to validate it
778
- let tag_mplace = self . mplace_field ( dest, 0 ) ?;
779
- let tag_value = self . read_scalar ( tag_mplace. into ( ) ) ?;
780
- let path = format ! ( "{}.TAG" , path) ;
781
- self . validate_scalar (
782
- tag_value, size, tag, & path, tag_mplace. layout . ty
783
- ) ?;
784
- // then we read it again to get the index, to continue
785
- let variant = self . read_discriminant_as_variant_index ( dest. into ( ) ) ?;
786
- let dest = self . mplace_downcast ( dest, variant) ?;
787
- trace ! ( "variant layout: {:#?}" , dest. layout) ;
788
- ( variant, dest)
789
- } ,
790
- layout:: Variants :: Single { index } => {
791
- ( index, dest)
792
- }
793
- } ;
794
-
795
- // Validate all fields
796
- match dest. layout . fields {
797
- // primitives are unions with zero fields
798
- layout:: FieldPlacement :: Union ( 0 ) => {
799
- match dest. layout . abi {
800
- // nothing to do, whatever the pointer points to, it is never going to be read
801
- layout:: Abi :: Uninhabited => validation_failure ! ( "a value of an uninhabited type" , path) ,
802
- // check that the scalar is a valid pointer or that its bit range matches the
803
- // expectation.
804
- layout:: Abi :: Scalar ( ref scalar_layout) => {
805
- let size = scalar_layout. value . size ( self ) ;
806
- let value = self . read_value ( dest. into ( ) ) ?;
807
- let scalar = value. to_scalar_or_undef ( ) ;
808
- self . validate_scalar ( scalar, size, scalar_layout, & path, dest. layout . ty ) ?;
809
- if scalar_layout. value == Primitive :: Pointer {
810
- // ignore integer pointers, we can't reason about the final hardware
811
- if let Scalar :: Ptr ( ptr) = scalar. not_undef ( ) ? {
812
- let alloc_kind = self . tcx . alloc_map . lock ( ) . get ( ptr. alloc_id ) ;
813
- if let Some ( AllocType :: Static ( did) ) = alloc_kind {
814
- // statics from other crates are already checked
815
- // extern statics should not be validated as they have no body
816
- if !did. is_local ( ) || self . tcx . is_foreign_item ( did) {
817
- return Ok ( ( ) ) ;
818
- }
819
- }
820
- if value. layout . ty . builtin_deref ( false ) . is_some ( ) {
821
- trace ! ( "Recursing below ptr {:#?}" , value) ;
822
- let ptr_place = self . ref_to_mplace ( value) ?;
823
- // we have not encountered this pointer+layout combination before
824
- if seen. insert ( ptr_place) {
825
- todo. push ( ( ptr_place, format ! ( "(*{})" , path) ) )
826
- }
827
- }
828
- }
829
- }
830
- Ok ( ( ) )
831
- } ,
832
- _ => bug ! ( "bad abi for FieldPlacement::Union(0): {:#?}" , dest. layout. abi) ,
833
- }
834
- }
835
- layout:: FieldPlacement :: Union ( _) => {
836
- // We can't check unions, their bits are allowed to be anything.
837
- // The fields don't need to correspond to any bit pattern of the union's fields.
838
- // See https://github.com/rust-lang/rust/issues/32836#issuecomment-406875389
839
- Ok ( ( ) )
840
- } ,
841
- layout:: FieldPlacement :: Array { count, .. } => {
842
- for i in 0 ..count {
843
- let mut path = path. clone ( ) ;
844
- self . dump_field_name ( & mut path, dest. layout . ty , i as usize , variant) . unwrap ( ) ;
845
- let field = self . mplace_field ( dest, i) ?;
846
- self . validate_mplace ( field, path, seen, todo) ?;
847
- }
848
- Ok ( ( ) )
849
- } ,
850
- layout:: FieldPlacement :: Arbitrary { ref offsets, .. } => {
851
- // fat pointers need special treatment
852
- match dest. layout . ty . builtin_deref ( false ) . map ( |tam| & tam. ty . sty ) {
853
- | Some ( ty:: TyStr )
854
- | Some ( ty:: TySlice ( _) ) => {
855
- // check the length (for nicer error messages)
856
- let len_mplace = self . mplace_field ( dest, 1 ) ?;
857
- let len = self . read_scalar ( len_mplace. into ( ) ) ?;
858
- let len = match len. to_bits ( len_mplace. layout . size ) {
859
- Err ( _) => return validation_failure ! ( "length is not a valid integer" , path) ,
860
- Ok ( len) => len as u64 ,
861
- } ;
862
- // get the fat ptr, and recursively check it
863
- let ptr = self . ref_to_mplace ( self . read_value ( dest. into ( ) ) ?) ?;
864
- assert_eq ! ( ptr. extra, PlaceExtra :: Length ( len) ) ;
865
- let unpacked_ptr = self . unpack_unsized_mplace ( ptr) ?;
866
- if seen. insert ( unpacked_ptr) {
867
- let mut path = path. clone ( ) ;
868
- self . dump_field_name ( & mut path, dest. layout . ty , 0 , 0 ) . unwrap ( ) ;
869
- todo. push ( ( unpacked_ptr, path) )
870
- }
871
- } ,
872
- Some ( ty:: TyDynamic ( ..) ) => {
873
- // check the vtable (for nicer error messages)
874
- let vtable = self . read_scalar ( self . mplace_field ( dest, 1 ) ?. into ( ) ) ?;
875
- let vtable = match vtable. to_ptr ( ) {
876
- Err ( _) => return validation_failure ! ( "vtable address is not a pointer" , path) ,
877
- Ok ( vtable) => vtable,
878
- } ;
879
- // get the fat ptr, and recursively check it
880
- let ptr = self . ref_to_mplace ( self . read_value ( dest. into ( ) ) ?) ?;
881
- assert_eq ! ( ptr. extra, PlaceExtra :: Vtable ( vtable) ) ;
882
- let unpacked_ptr = self . unpack_unsized_mplace ( ptr) ?;
883
- if seen. insert ( unpacked_ptr) {
884
- let mut path = path. clone ( ) ;
885
- self . dump_field_name ( & mut path, dest. layout . ty , 0 , 0 ) . unwrap ( ) ;
886
- todo. push ( ( unpacked_ptr, path) )
887
- }
888
- // FIXME: More checks for the vtable... making sure it is exactly
889
- // the one one would expect for this type.
890
- } ,
891
- Some ( ty) =>
892
- bug ! ( "Unexpected fat pointer target type {:?}" , ty) ,
893
- None => {
894
- // Not a pointer, perform regular aggregate handling below
895
- for i in 0 ..offsets. len ( ) {
896
- let mut path = path. clone ( ) ;
897
- self . dump_field_name ( & mut path, dest. layout . ty , i, variant) . unwrap ( ) ;
898
- let field = self . mplace_field ( dest, i as u64 ) ?;
899
- self . validate_mplace ( field, path, seen, todo) ?;
900
- }
901
- // FIXME: For a TyStr, check that this is valid UTF-8.
902
- } ,
903
- }
904
-
905
- Ok ( ( ) )
906
- }
907
- }
908
- }
909
-
910
648
#[ inline( always) ]
911
649
pub fn frame ( & self ) -> & Frame < ' mir , ' tcx > {
912
650
self . stack . last ( ) . expect ( "no call frames exist" )
@@ -1041,72 +779,5 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
1041
779
pub fn truncate ( & self , value : u128 , ty : TyLayout < ' _ > ) -> u128 {
1042
780
truncate ( value, ty. size )
1043
781
}
1044
-
1045
- fn dump_field_name ( & self , s : & mut String , ty : Ty < ' tcx > , i : usize , variant : usize ) -> :: std:: fmt:: Result {
1046
- match ty. sty {
1047
- ty:: TyBool |
1048
- ty:: TyChar |
1049
- ty:: TyInt ( _) |
1050
- ty:: TyUint ( _) |
1051
- ty:: TyFloat ( _) |
1052
- ty:: TyFnPtr ( _) |
1053
- ty:: TyNever |
1054
- ty:: TyFnDef ( ..) |
1055
- ty:: TyGeneratorWitness ( ..) |
1056
- ty:: TyForeign ( ..) |
1057
- ty:: TyDynamic ( ..) => {
1058
- bug ! ( "field_name({:?}): not applicable" , ty)
1059
- }
1060
-
1061
- // Potentially-fat pointers.
1062
- ty:: TyRef ( _, pointee, _) |
1063
- ty:: TyRawPtr ( ty:: TypeAndMut { ty : pointee, .. } ) => {
1064
- assert ! ( i < 2 ) ;
1065
-
1066
- // Reuse the fat *T type as its own thin pointer data field.
1067
- // This provides information about e.g. DST struct pointees
1068
- // (which may have no non-DST form), and will work as long
1069
- // as the `Abi` or `FieldPlacement` is checked by users.
1070
- if i == 0 {
1071
- return write ! ( s, ".data_ptr" ) ;
1072
- }
1073
-
1074
- match self . tcx . struct_tail ( pointee) . sty {
1075
- ty:: TySlice ( _) |
1076
- ty:: TyStr => write ! ( s, ".len" ) ,
1077
- ty:: TyDynamic ( ..) => write ! ( s, ".vtable_ptr" ) ,
1078
- _ => bug ! ( "field_name({:?}): not applicable" , ty)
1079
- }
1080
- }
1081
-
1082
- // Arrays and slices.
1083
- ty:: TyArray ( _, _) |
1084
- ty:: TySlice ( _) |
1085
- ty:: TyStr => write ! ( s, "[{}]" , i) ,
1086
-
1087
- // generators and closures.
1088
- ty:: TyClosure ( def_id, _) | ty:: TyGenerator ( def_id, _, _) => {
1089
- let node_id = self . tcx . hir . as_local_node_id ( def_id) . unwrap ( ) ;
1090
- let freevar = self . tcx . with_freevars ( node_id, |fv| fv[ i] ) ;
1091
- write ! ( s, ".upvar({})" , self . tcx. hir. name( freevar. var_id( ) ) )
1092
- }
1093
-
1094
- ty:: TyTuple ( _) => write ! ( s, ".{}" , i) ,
1095
-
1096
- // enums
1097
- ty:: TyAdt ( def, ..) if def. is_enum ( ) => {
1098
- let variant = & def. variants [ variant] ;
1099
- write ! ( s, ".{}::{}" , variant. name, variant. fields[ i] . ident)
1100
- }
1101
-
1102
- // other ADTs.
1103
- ty:: TyAdt ( def, _) => write ! ( s, ".{}" , def. non_enum_variant( ) . fields[ i] . ident) ,
1104
-
1105
- ty:: TyProjection ( _) | ty:: TyAnon ( ..) | ty:: TyParam ( _) |
1106
- ty:: TyInfer ( _) | ty:: TyError => {
1107
- bug ! ( "dump_field_name: unexpected type `{}`" , ty)
1108
- }
1109
- }
1110
- }
1111
782
}
1112
783
0 commit comments