@@ -14,7 +14,6 @@ private import codeql.rust.controlflow.CfgNodes
14
14
private import codeql.rust.dataflow.Ssa
15
15
private import codeql.rust.dataflow.FlowSummary
16
16
private import FlowSummaryImpl as FlowSummaryImpl
17
- private import codeql.rust.elements.internal.PathResolution as PathResolution
18
17
19
18
/**
20
19
* A return kind. A return kind describes how a value can be returned from a
@@ -661,7 +660,7 @@ private module VariantInLib {
661
660
}
662
661
663
662
/** A tuple variant from library code. */
664
- class VariantInLibTupleFieldContent extends VariantContent , TVariantInLibTupleFieldContent {
663
+ class VariantInLibTupleFieldContent extends Content , TVariantInLibTupleFieldContent {
665
664
private VariantInLib:: VariantInLib v ;
666
665
private int pos_ ;
667
666
@@ -740,82 +739,71 @@ abstract class Content extends TContent {
740
739
abstract Location getLocation ( ) ;
741
740
}
742
741
743
- /**
744
- * A variant of an `enum`. In addition to the variant itself, this also includes the
745
- * position (for tuple variants) or the field name (for record variants).
746
- */
747
- abstract class VariantContent extends Content { }
748
-
749
- private TupleField getVariantTupleField ( Variant v , int i ) {
750
- result = v .getFieldList ( ) .( TupleFieldList ) .getField ( i )
742
+ abstract class FieldContent extends Content {
743
+ pragma [ nomagic]
744
+ abstract FieldExprCfgNode getAnAccess ( ) ;
751
745
}
752
746
753
- /** A tuple variant. */
754
- private class VariantTupleFieldContent extends VariantContent , TVariantTupleFieldContent {
755
- private Variant v ;
756
- private int pos_ ;
747
+ /** A tuple field belonging to either a variant or a struct. */
748
+ class TupleFieldContent extends FieldContent , TTupleFieldContent {
749
+ private TupleField field ;
750
+
751
+ TupleFieldContent ( ) { this = TTupleFieldContent ( field ) }
752
+
753
+ predicate isVariantField ( Variant v , int pos ) { field .isVariantField ( v , pos ) }
757
754
758
- VariantTupleFieldContent ( ) { this = TVariantTupleFieldContent ( v , pos_ ) }
755
+ predicate isStructField ( Struct s , int pos ) { field . isStructField ( s , pos ) }
759
756
760
- Variant getVariant ( int pos ) { result = v and pos = pos_ }
757
+ override FieldExprCfgNode getAnAccess ( ) { none ( ) } // TODO
761
758
762
759
final override string toString ( ) {
763
- exists ( string name |
764
- name = v .getName ( ) .getText ( ) and
760
+ exists ( Variant v , int pos , string vname |
761
+ this .isVariantField ( v , pos ) and
762
+ vname = v .getName ( ) .getText ( ) and
765
763
// only print indices when the arity is > 1
766
- if exists ( getVariantTupleField ( v , 1 ) ) then result = name + "(" + pos_ + ")" else result = name
764
+ if exists ( v .getTupleField ( 1 ) ) then result = vname + "(" + pos + ")" else result = vname
765
+ )
766
+ or
767
+ exists ( Struct s , int pos , string sname |
768
+ this .isStructField ( s , pos ) and
769
+ sname = s .getName ( ) .getText ( ) and
770
+ // only print indices when the arity is > 1
771
+ if exists ( s .getTupleField ( 1 ) ) then result = sname + "(" + pos + ")" else result = sname
767
772
)
768
773
}
769
774
770
- final override Location getLocation ( ) { result = getVariantTupleField ( v , pos_ ) .getLocation ( ) }
775
+ final override Location getLocation ( ) { result = field .getLocation ( ) }
771
776
}
772
777
773
- private RecordField getVariantRecordField ( Variant v , string field ) {
774
- result = v .getFieldList ( ) .( RecordFieldList ) .getAField ( ) and
775
- field = result .getName ( ) .getText ( )
776
- }
778
+ /** A record field belonging to either a variant or a struct. */
779
+ class RecordFieldContent extends FieldContent , TRecordFieldContent {
780
+ private RecordField field ;
781
+
782
+ RecordFieldContent ( ) { this = TRecordFieldContent ( field ) }
777
783
778
- /** A record variant. */
779
- private class VariantRecordFieldContent extends VariantContent , TVariantRecordFieldContent {
780
- private Variant v ;
781
- private string field_ ;
784
+ predicate isVariantField ( Variant v , string name ) { field .isVariantField ( v , name ) }
782
785
783
- VariantRecordFieldContent ( ) { this = TVariantRecordFieldContent ( v , field_ ) }
786
+ predicate isStructField ( Struct s , string name ) { field . isStructField ( s , name ) }
784
787
785
- Variant getVariant ( string field ) { result = v and field = field_ }
788
+ override FieldExprCfgNode getAnAccess ( ) { none ( ) } // TODO
786
789
787
790
final override string toString ( ) {
788
- exists ( string name |
789
- name = v .getName ( ) .getText ( ) and
791
+ exists ( Variant v , string name , string vname |
792
+ this .isVariantField ( v , name ) and
793
+ vname = v .getName ( ) .getText ( ) and
790
794
// only print field when the arity is > 1
791
- if strictcount ( string f | exists ( getVariantRecordField ( v , f ) ) ) > 1
792
- then result = name + "{" + field_ + "}"
793
- else result = name
795
+ if strictcount ( v .getRecordField ( _) ) > 1 then result = vname + "." + name else result = vname
794
796
)
795
- }
796
-
797
- final override Location getLocation ( ) {
798
- result = getVariantRecordField ( v , field_ ) .getName ( ) .getLocation ( )
799
- }
800
- }
801
-
802
- /** Content stored in a field on a struct. */
803
- class StructFieldContent extends Content , TStructFieldContent {
804
- private Struct s ;
805
- private string field_ ;
806
-
807
- StructFieldContent ( ) { this = TStructFieldContent ( s , field_ ) }
808
-
809
- Struct getStruct ( string field ) { result = s and field = field_ }
810
-
811
- override string toString ( ) { result = s .getName ( ) .getText ( ) + "." + field_ .toString ( ) }
812
-
813
- override Location getLocation ( ) {
814
- exists ( Name f | f = s .getFieldList ( ) .( RecordFieldList ) .getAField ( ) .getName ( ) |
815
- f .getText ( ) = field_ and
816
- result = f .getLocation ( )
797
+ or
798
+ exists ( Struct s , string name , string sname |
799
+ this .isStructField ( s , name ) and
800
+ sname = s .getName ( ) .getText ( ) and
801
+ // only print field when the arity is > 1
802
+ if strictcount ( s .getRecordField ( _) ) > 1 then result = sname + "." + name else result = sname
817
803
)
818
804
}
805
+
806
+ final override Location getLocation ( ) { result = field .getLocation ( ) }
819
807
}
820
808
821
809
/** A captured variable. */
@@ -859,23 +847,23 @@ final class ElementContent extends Content, TElementContent {
859
847
* NOTE: Unlike `struct`s and `enum`s tuples are structural and not nominal,
860
848
* hence we don't store a canonical path for them.
861
849
*/
862
- final class TuplePositionContent extends Content , TTuplePositionContent {
850
+ final class TuplePositionContent extends FieldContent , TTuplePositionContent {
863
851
private int pos ;
864
852
865
853
TuplePositionContent ( ) { this = TTuplePositionContent ( pos ) }
866
854
867
855
int getPosition ( ) { result = pos }
868
856
857
+ override FieldExprCfgNode getAnAccess ( ) {
858
+ // TODO: limit to tuple types
859
+ result .getNameRef ( ) .getText ( ) .toInt ( ) = pos
860
+ }
861
+
869
862
override string toString ( ) { result = "tuple." + pos .toString ( ) }
870
863
871
864
override Location getLocation ( ) { result instanceof EmptyLocation }
872
865
}
873
866
874
- /** Holds if `access` indexes a tuple at an index corresponding to `c`. */
875
- private predicate fieldTuplePositionContent ( FieldExprCfgNode access , TuplePositionContent c ) {
876
- access .getNameRef ( ) .getText ( ) .toInt ( ) = c .getPosition ( )
877
- }
878
-
879
867
/** A value that represents a set of `Content`s. */
880
868
abstract class ContentSet extends TContentSet {
881
869
/** Gets a textual representation of this element. */
@@ -1098,23 +1086,6 @@ module RustDataFlow implements InputSig<Location> {
1098
1086
node2 .( Node:: FlowSummaryNode ) .getSummaryNode ( ) )
1099
1087
}
1100
1088
1101
- /** Gets the item that `p` resolves to, if any. */
1102
- private PathResolution:: ItemNode resolvePath ( PathAstNode p ) {
1103
- result = PathResolution:: resolvePath ( p .getPath ( ) )
1104
- }
1105
-
1106
- /** Holds if `p` destructs an enum variant `v`. */
1107
- pragma [ nomagic]
1108
- private predicate tupleVariantDestruction ( TupleStructPat p , Variant v ) { v = resolvePath ( p ) }
1109
-
1110
- /** Holds if `p` destructs an enum variant `v`. */
1111
- pragma [ nomagic]
1112
- private predicate recordVariantDestruction ( RecordPat p , Variant v ) { v = resolvePath ( p ) }
1113
-
1114
- /** Holds if `p` destructs a struct `s`. */
1115
- pragma [ nomagic]
1116
- private predicate structDestruction ( RecordPat p , Struct s ) { s = resolvePath ( p ) }
1117
-
1118
1089
/**
1119
1090
* Holds if data can flow from `node1` to `node2` via a read of `c`. Thus,
1120
1091
* `node1` references an object with a content `c.getAReadContent()` whose
@@ -1126,7 +1097,7 @@ module RustDataFlow implements InputSig<Location> {
1126
1097
pat = node1 .asPat ( ) and
1127
1098
node2 .asPat ( ) = pat .getField ( pos )
1128
1099
|
1129
- tupleVariantDestruction ( pat .getPat ( ) , c . ( VariantTupleFieldContent ) . getVariant ( pos ) )
1100
+ c = TTupleFieldContent ( pat .getTupleStructPat ( ) . getTupleField ( pos ) )
1130
1101
or
1131
1102
VariantInLib:: tupleVariantCanonicalDestruction ( pat .getPat ( ) , c , pos )
1132
1103
)
@@ -1139,25 +1110,17 @@ module RustDataFlow implements InputSig<Location> {
1139
1110
or
1140
1111
exists ( RecordPatCfgNode pat , string field |
1141
1112
pat = node1 .asPat ( ) and
1142
- (
1143
- // Pattern destructs a struct-like variant.
1144
- recordVariantDestruction ( pat .getPat ( ) , c .( VariantRecordFieldContent ) .getVariant ( field ) )
1145
- or
1146
- // Pattern destructs a struct.
1147
- structDestruction ( pat .getPat ( ) , c .( StructFieldContent ) .getStruct ( field ) )
1148
- ) and
1113
+ c = TRecordFieldContent ( pat .getRecordPat ( ) .getRecordField ( field ) ) and
1149
1114
node2 .asPat ( ) = pat .getFieldPat ( field )
1150
1115
)
1151
1116
or
1152
1117
c instanceof ReferenceContent and
1153
1118
node1 .asPat ( ) .( RefPatCfgNode ) .getPat ( ) = node2 .asPat ( )
1154
1119
or
1155
1120
exists ( FieldExprCfgNode access |
1156
- // Read of a tuple entry
1157
- fieldTuplePositionContent ( access , c ) and
1158
- // TODO: Handle read of a struct field.
1159
1121
node1 .asExpr ( ) = access .getExpr ( ) and
1160
- node2 .asExpr ( ) = access
1122
+ node2 .asExpr ( ) = access and
1123
+ access = c .( FieldContent ) .getAnAccess ( )
1161
1124
)
1162
1125
or
1163
1126
exists ( IndexExprCfgNode arr |
@@ -1199,26 +1162,13 @@ module RustDataFlow implements InputSig<Location> {
1199
1162
cs , node2 .( Node:: FlowSummaryNode ) .getSummaryNode ( ) )
1200
1163
}
1201
1164
1202
- /** Holds if `ce` constructs an enum value of type `v`. */
1203
- pragma [ nomagic]
1204
- private predicate tupleVariantConstruction ( CallExpr ce , Variant v ) {
1205
- v = resolvePath ( ce .getFunction ( ) .( PathExpr ) )
1206
- }
1207
-
1208
- /** Holds if `re` constructs an enum value of type `v`. */
1209
1165
pragma [ nomagic]
1210
- private predicate recordVariantConstruction ( RecordExpr re , Variant v ) { v = resolvePath ( re ) }
1211
-
1212
- /** Holds if `re` constructs a struct value of type `s`. */
1213
- pragma [ nomagic]
1214
- private predicate structConstruction ( RecordExpr re , Struct s ) { s = resolvePath ( re ) }
1215
-
1216
- private predicate tupleAssignment ( Node node1 , Node node2 , TuplePositionContent c ) {
1166
+ private predicate fieldAssignment ( Node node1 , Node node2 , FieldContent c ) {
1217
1167
exists ( AssignmentExprCfgNode assignment , FieldExprCfgNode access |
1218
1168
assignment .getLhs ( ) = access and
1219
- fieldTuplePositionContent ( access , c ) and
1220
1169
node1 .asExpr ( ) = assignment .getRhs ( ) and
1221
- node2 .asExpr ( ) = access .getExpr ( )
1170
+ node2 .asExpr ( ) = access .getExpr ( ) and
1171
+ access = c .getAnAccess ( )
1222
1172
)
1223
1173
}
1224
1174
@@ -1228,20 +1178,13 @@ module RustDataFlow implements InputSig<Location> {
1228
1178
node1 .asExpr ( ) = call .getArgument ( pos ) and
1229
1179
node2 .asExpr ( ) = call
1230
1180
|
1231
- tupleVariantConstruction ( call .getCallExpr ( ) , c . ( VariantTupleFieldContent ) . getVariant ( pos ) )
1181
+ c = TTupleFieldContent ( call .getCallExpr ( ) . getTupleField ( pos ) )
1232
1182
or
1233
1183
VariantInLib:: tupleVariantCanonicalConstruction ( call .getCallExpr ( ) , c , pos )
1234
1184
)
1235
1185
or
1236
1186
exists ( RecordExprCfgNode re , string field |
1237
- (
1238
- // Expression is for a struct-like enum variant.
1239
- recordVariantConstruction ( re .getRecordExpr ( ) ,
1240
- c .( VariantRecordFieldContent ) .getVariant ( field ) )
1241
- or
1242
- // Expression is for a struct.
1243
- structConstruction ( re .getRecordExpr ( ) , c .( StructFieldContent ) .getStruct ( field ) )
1244
- ) and
1187
+ c = TRecordFieldContent ( re .getRecordExpr ( ) .getRecordField ( field ) ) and
1245
1188
node1 .asExpr ( ) = re .getFieldExpr ( field ) and
1246
1189
node2 .asExpr ( ) = re
1247
1190
)
@@ -1258,7 +1201,7 @@ module RustDataFlow implements InputSig<Location> {
1258
1201
node2 .asExpr ( ) .( ArrayListExprCfgNode ) .getAnExpr ( )
1259
1202
]
1260
1203
or
1261
- tupleAssignment ( node1 , node2 .( PostUpdateNode ) .getPreUpdateNode ( ) , c )
1204
+ fieldAssignment ( node1 , node2 .( PostUpdateNode ) .getPreUpdateNode ( ) , c )
1262
1205
or
1263
1206
exists ( AssignmentExprCfgNode assignment , IndexExprCfgNode index |
1264
1207
c instanceof ElementContent and
@@ -1294,7 +1237,7 @@ module RustDataFlow implements InputSig<Location> {
1294
1237
* in `x.f = newValue`.
1295
1238
*/
1296
1239
predicate clearsContent ( Node n , ContentSet cs ) {
1297
- tupleAssignment ( _, n , cs .( SingletonContentSet ) .getContent ( ) )
1240
+ fieldAssignment ( _, n , cs .( SingletonContentSet ) .getContent ( ) )
1298
1241
or
1299
1242
FlowSummaryImpl:: Private:: Steps:: summaryClearsContent ( n .( Node:: FlowSummaryNode ) .getSummaryNode ( ) ,
1300
1243
cs )
@@ -1600,10 +1543,10 @@ private module Cached {
1600
1543
1601
1544
cached
1602
1545
newtype TContent =
1603
- TVariantTupleFieldContent ( Variant v , int pos ) { exists ( getVariantTupleField ( v , pos ) ) } or
1546
+ TTupleFieldContent ( TupleField field ) or
1547
+ TRecordFieldContent ( RecordField field ) or
1604
1548
// TODO: Remove once library types are extracted
1605
1549
TVariantInLibTupleFieldContent ( VariantInLib:: VariantInLib v , int pos ) { pos = v .getAPosition ( ) } or
1606
- TVariantRecordFieldContent ( Variant v , string field ) { exists ( getVariantRecordField ( v , field ) ) } or
1607
1550
TElementContent ( ) or
1608
1551
TTuplePositionContent ( int pos ) {
1609
1552
pos in [ 0 .. max ( [
@@ -1612,9 +1555,6 @@ private module Cached {
1612
1555
]
1613
1556
) ]
1614
1557
} or
1615
- TStructFieldContent ( Struct s , string field ) {
1616
- field = s .getFieldList ( ) .( RecordFieldList ) .getAField ( ) .getName ( ) .getText ( )
1617
- } or
1618
1558
TCapturedVariableContent ( VariableCapture:: CapturedVariable v ) or
1619
1559
TReferenceContent ( )
1620
1560
0 commit comments