@@ -14,7 +14,6 @@ private import codeql.rust.controlflow.CfgNodes
1414private import codeql.rust.dataflow.Ssa
1515private import codeql.rust.dataflow.FlowSummary
1616private import FlowSummaryImpl as FlowSummaryImpl
17- private import codeql.rust.elements.internal.PathResolution as PathResolution
1817
1918/**
2019 * A return kind. A return kind describes how a value can be returned from a
@@ -661,7 +660,7 @@ private module VariantInLib {
661660 }
662661
663662 /** A tuple variant from library code. */
664- class VariantInLibTupleFieldContent extends VariantContent , TVariantInLibTupleFieldContent {
663+ class VariantInLibTupleFieldContent extends Content , TVariantInLibTupleFieldContent {
665664 private VariantInLib:: VariantInLib v ;
666665 private int pos_ ;
667666
@@ -740,82 +739,71 @@ abstract class Content extends TContent {
740739 abstract Location getLocation ( ) ;
741740}
742741
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 ( ) ;
751745}
752746
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 ) }
757754
758- VariantTupleFieldContent ( ) { this = TVariantTupleFieldContent ( v , pos_ ) }
755+ predicate isStructField ( Struct s , int pos ) { field . isStructField ( s , pos ) }
759756
760- Variant getVariant ( int pos ) { result = v and pos = pos_ }
757+ override FieldExprCfgNode getAnAccess ( ) { none ( ) } // TODO
761758
762759 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
765763 // 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
767772 )
768773 }
769774
770- final override Location getLocation ( ) { result = getVariantTupleField ( v , pos_ ) .getLocation ( ) }
775+ final override Location getLocation ( ) { result = field .getLocation ( ) }
771776}
772777
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 ) }
777783
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 ) }
782785
783- VariantRecordFieldContent ( ) { this = TVariantRecordFieldContent ( v , field_ ) }
786+ predicate isStructField ( Struct s , string name ) { field . isStructField ( s , name ) }
784787
785- Variant getVariant ( string field ) { result = v and field = field_ }
788+ override FieldExprCfgNode getAnAccess ( ) { none ( ) } // TODO
786789
787790 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
790794 // 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
794796 )
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
817803 )
818804 }
805+
806+ final override Location getLocation ( ) { result = field .getLocation ( ) }
819807}
820808
821809/** A captured variable. */
@@ -859,23 +847,23 @@ final class ElementContent extends Content, TElementContent {
859847 * NOTE: Unlike `struct`s and `enum`s tuples are structural and not nominal,
860848 * hence we don't store a canonical path for them.
861849 */
862- final class TuplePositionContent extends Content , TTuplePositionContent {
850+ final class TuplePositionContent extends FieldContent , TTuplePositionContent {
863851 private int pos ;
864852
865853 TuplePositionContent ( ) { this = TTuplePositionContent ( pos ) }
866854
867855 int getPosition ( ) { result = pos }
868856
857+ override FieldExprCfgNode getAnAccess ( ) {
858+ // TODO: limit to tuple types
859+ result .getNameRef ( ) .getText ( ) .toInt ( ) = pos
860+ }
861+
869862 override string toString ( ) { result = "tuple." + pos .toString ( ) }
870863
871864 override Location getLocation ( ) { result instanceof EmptyLocation }
872865}
873866
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-
879867/** A value that represents a set of `Content`s. */
880868abstract class ContentSet extends TContentSet {
881869 /** Gets a textual representation of this element. */
@@ -1098,23 +1086,6 @@ module RustDataFlow implements InputSig<Location> {
10981086 node2 .( Node:: FlowSummaryNode ) .getSummaryNode ( ) )
10991087 }
11001088
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-
11181089 /**
11191090 * Holds if data can flow from `node1` to `node2` via a read of `c`. Thus,
11201091 * `node1` references an object with a content `c.getAReadContent()` whose
@@ -1126,7 +1097,7 @@ module RustDataFlow implements InputSig<Location> {
11261097 pat = node1 .asPat ( ) and
11271098 node2 .asPat ( ) = pat .getField ( pos )
11281099 |
1129- tupleVariantDestruction ( pat .getPat ( ) , c . ( VariantTupleFieldContent ) . getVariant ( pos ) )
1100+ c = TTupleFieldContent ( pat .getTupleStructPat ( ) . getTupleField ( pos ) )
11301101 or
11311102 VariantInLib:: tupleVariantCanonicalDestruction ( pat .getPat ( ) , c , pos )
11321103 )
@@ -1139,25 +1110,17 @@ module RustDataFlow implements InputSig<Location> {
11391110 or
11401111 exists ( RecordPatCfgNode pat , string field |
11411112 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
11491114 node2 .asPat ( ) = pat .getFieldPat ( field )
11501115 )
11511116 or
11521117 c instanceof ReferenceContent and
11531118 node1 .asPat ( ) .( RefPatCfgNode ) .getPat ( ) = node2 .asPat ( )
11541119 or
11551120 exists ( FieldExprCfgNode access |
1156- // Read of a tuple entry
1157- fieldTuplePositionContent ( access , c ) and
1158- // TODO: Handle read of a struct field.
11591121 node1 .asExpr ( ) = access .getExpr ( ) and
1160- node2 .asExpr ( ) = access
1122+ node2 .asExpr ( ) = access and
1123+ access = c .( FieldContent ) .getAnAccess ( )
11611124 )
11621125 or
11631126 exists ( IndexExprCfgNode arr |
@@ -1199,26 +1162,13 @@ module RustDataFlow implements InputSig<Location> {
11991162 cs , node2 .( Node:: FlowSummaryNode ) .getSummaryNode ( ) )
12001163 }
12011164
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`. */
12091165 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 ) {
12171167 exists ( AssignmentExprCfgNode assignment , FieldExprCfgNode access |
12181168 assignment .getLhs ( ) = access and
1219- fieldTuplePositionContent ( access , c ) and
12201169 node1 .asExpr ( ) = assignment .getRhs ( ) and
1221- node2 .asExpr ( ) = access .getExpr ( )
1170+ node2 .asExpr ( ) = access .getExpr ( ) and
1171+ access = c .getAnAccess ( )
12221172 )
12231173 }
12241174
@@ -1228,20 +1178,13 @@ module RustDataFlow implements InputSig<Location> {
12281178 node1 .asExpr ( ) = call .getArgument ( pos ) and
12291179 node2 .asExpr ( ) = call
12301180 |
1231- tupleVariantConstruction ( call .getCallExpr ( ) , c . ( VariantTupleFieldContent ) . getVariant ( pos ) )
1181+ c = TTupleFieldContent ( call .getCallExpr ( ) . getTupleField ( pos ) )
12321182 or
12331183 VariantInLib:: tupleVariantCanonicalConstruction ( call .getCallExpr ( ) , c , pos )
12341184 )
12351185 or
12361186 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
12451188 node1 .asExpr ( ) = re .getFieldExpr ( field ) and
12461189 node2 .asExpr ( ) = re
12471190 )
@@ -1258,7 +1201,7 @@ module RustDataFlow implements InputSig<Location> {
12581201 node2 .asExpr ( ) .( ArrayListExprCfgNode ) .getAnExpr ( )
12591202 ]
12601203 or
1261- tupleAssignment ( node1 , node2 .( PostUpdateNode ) .getPreUpdateNode ( ) , c )
1204+ fieldAssignment ( node1 , node2 .( PostUpdateNode ) .getPreUpdateNode ( ) , c )
12621205 or
12631206 exists ( AssignmentExprCfgNode assignment , IndexExprCfgNode index |
12641207 c instanceof ElementContent and
@@ -1294,7 +1237,7 @@ module RustDataFlow implements InputSig<Location> {
12941237 * in `x.f = newValue`.
12951238 */
12961239 predicate clearsContent ( Node n , ContentSet cs ) {
1297- tupleAssignment ( _, n , cs .( SingletonContentSet ) .getContent ( ) )
1240+ fieldAssignment ( _, n , cs .( SingletonContentSet ) .getContent ( ) )
12981241 or
12991242 FlowSummaryImpl:: Private:: Steps:: summaryClearsContent ( n .( Node:: FlowSummaryNode ) .getSummaryNode ( ) ,
13001243 cs )
@@ -1600,10 +1543,10 @@ private module Cached {
16001543
16011544 cached
16021545 newtype TContent =
1603- TVariantTupleFieldContent ( Variant v , int pos ) { exists ( getVariantTupleField ( v , pos ) ) } or
1546+ TTupleFieldContent ( TupleField field ) or
1547+ TRecordFieldContent ( RecordField field ) or
16041548 // TODO: Remove once library types are extracted
16051549 TVariantInLibTupleFieldContent ( VariantInLib:: VariantInLib v , int pos ) { pos = v .getAPosition ( ) } or
1606- TVariantRecordFieldContent ( Variant v , string field ) { exists ( getVariantRecordField ( v , field ) ) } or
16071550 TElementContent ( ) or
16081551 TTuplePositionContent ( int pos ) {
16091552 pos in [ 0 .. max ( [
@@ -1612,9 +1555,6 @@ private module Cached {
16121555 ]
16131556 ) ]
16141557 } or
1615- TStructFieldContent ( Struct s , string field ) {
1616- field = s .getFieldList ( ) .( RecordFieldList ) .getAField ( ) .getName ( ) .getText ( )
1617- } or
16181558 TCapturedVariableContent ( VariableCapture:: CapturedVariable v ) or
16191559 TReferenceContent ( )
16201560
0 commit comments