Skip to content

Commit aeca2b2

Browse files
committed
temp
1 parent b01c74c commit aeca2b2

File tree

13 files changed

+332
-69
lines changed

13 files changed

+332
-69
lines changed

rust/ql/lib/codeql/rust/controlflow/CfgNodes.qll

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,12 @@ final class RecordPatCfgNode extends Nodes::RecordPatCfgNode {
264264
PatCfgNode getFieldPat(string field) {
265265
exists(RecordPatField rpf |
266266
rpf = node.getRecordPatFieldList().getAField() and
267-
any(ChildMapping mapping).hasCfgChild(node, rpf.getPat(), this, result) and
267+
any(ChildMapping mapping).hasCfgChild(node, rpf.getPat(), this, result)
268+
|
268269
field = rpf.getNameRef().getText()
270+
or
271+
not rpf.hasNameRef() and
272+
field = result.(IdentPatCfgNode).getName().getText()
269273
)
270274
}
271275
}

rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll

Lines changed: 62 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ private import codeql.rust.dataflow.Ssa
1515
private import codeql.rust.dataflow.FlowSummary
1616
private import FlowSummaryImpl as FlowSummaryImpl
1717
private import codeql.rust.elements.internal.PathResolution as PathResolution
18+
private import codeql.rust.elements.internal.TypeInference as TypeInference
1819

1920
/**
2021
* A return kind. A return kind describes how a value can be returned from a
@@ -738,10 +739,6 @@ abstract class Content extends TContent {
738739
*/
739740
abstract class VariantContent extends Content { }
740741

741-
private TupleField getVariantTupleField(Variant v, int i) {
742-
result = v.getFieldList().(TupleFieldList).getField(i)
743-
}
744-
745742
/** A tuple variant. */
746743
private class VariantTupleFieldContent extends VariantContent, TVariantTupleFieldContent {
747744
private Variant v;
@@ -755,16 +752,11 @@ private class VariantTupleFieldContent extends VariantContent, TVariantTupleFiel
755752
exists(string name |
756753
name = v.getName().getText() and
757754
// only print indices when the arity is > 1
758-
if exists(getVariantTupleField(v, 1)) then result = name + "(" + pos_ + ")" else result = name
755+
if exists(v.getTupleField(1)) then result = name + "(" + pos_ + ")" else result = name
759756
)
760757
}
761758

762-
final override Location getLocation() { result = getVariantTupleField(v, pos_).getLocation() }
763-
}
764-
765-
private RecordField getVariantRecordField(Variant v, string field) {
766-
result = v.getFieldList().(RecordFieldList).getAField() and
767-
field = result.getName().getText()
759+
final override Location getLocation() { result = v.getTupleField(pos_).getLocation() }
768760
}
769761

770762
/** A record variant. */
@@ -780,34 +772,56 @@ private class VariantRecordFieldContent extends VariantContent, TVariantRecordFi
780772
exists(string name |
781773
name = v.getName().getText() and
782774
// only print field when the arity is > 1
783-
if strictcount(string f | exists(getVariantRecordField(v, f))) > 1
775+
if strictcount(v.getRecordField(_)) > 1
784776
then result = name + "{" + field_ + "}"
785777
else result = name
786778
)
787779
}
788780

789781
final override Location getLocation() {
790-
result = getVariantRecordField(v, field_).getName().getLocation()
782+
result = v.getRecordField(field_).getName().getLocation()
783+
}
784+
}
785+
786+
abstract private class FieldContent extends Content {
787+
pragma[nomagic]
788+
abstract FieldExprCfgNode getAnAccess();
789+
}
790+
791+
/** Content stored in a tuple field on a struct. */
792+
private class StructTupleFieldContent extends FieldContent, TStructTupleFieldContent {
793+
private Struct s;
794+
private int pos_;
795+
796+
StructTupleFieldContent() { this = TStructTupleFieldContent(s, pos_) }
797+
798+
Struct getStruct(int pos) { result = s and pos = pos_ }
799+
800+
override FieldExprCfgNode getAnAccess() {
801+
s.getTupleField(pos_) = TypeInference::resolveTupleFieldExpr(result.getFieldExpr())
791802
}
803+
804+
override string toString() { result = s.getName().getText() + "." + pos_.toString() }
805+
806+
override Location getLocation() { result = s.getTupleField(pos_).getLocation() }
792807
}
793808

794-
/** Content stored in a field on a struct. */
795-
private class StructFieldContent extends Content, TStructFieldContent {
809+
/** Content stored in a record field on a struct. */
810+
private class StructRecordFieldContent extends FieldContent, TStructRecordFieldContent {
796811
private Struct s;
797812
private string field_;
798813

799-
StructFieldContent() { this = TStructFieldContent(s, field_) }
814+
StructRecordFieldContent() { this = TStructRecordFieldContent(s, field_) }
800815

801816
Struct getStruct(string field) { result = s and field = field_ }
802817

818+
override FieldExprCfgNode getAnAccess() {
819+
s.getRecordField(field_) = TypeInference::resolveRecordFieldExpr(result.getFieldExpr())
820+
}
821+
803822
override string toString() { result = s.getName().getText() + "." + field_.toString() }
804823

805-
override Location getLocation() {
806-
exists(Name f | f = s.getFieldList().(RecordFieldList).getAField().getName() |
807-
f.getText() = field_ and
808-
result = f.getLocation()
809-
)
810-
}
824+
override Location getLocation() { result = s.getRecordField(field_).getName().getLocation() }
811825
}
812826

813827
/** A captured variable. */
@@ -851,23 +865,23 @@ final class ElementContent extends Content, TElementContent {
851865
* NOTE: Unlike `struct`s and `enum`s tuples are structural and not nominal,
852866
* hence we don't store a canonical path for them.
853867
*/
854-
final class TuplePositionContent extends Content, TTuplePositionContent {
868+
final class TuplePositionContent extends FieldContent, TTuplePositionContent {
855869
private int pos;
856870

857871
TuplePositionContent() { this = TTuplePositionContent(pos) }
858872

859873
int getPosition() { result = pos }
860874

875+
override FieldExprCfgNode getAnAccess() {
876+
// todo: limit to tuple types
877+
result.getNameRef().getText().toInt() = pos
878+
}
879+
861880
override string toString() { result = "tuple." + pos.toString() }
862881

863882
override Location getLocation() { result instanceof EmptyLocation }
864883
}
865884

866-
/** Holds if `access` indexes a tuple at an index corresponding to `c`. */
867-
private predicate fieldTuplePositionContent(FieldExprCfgNode access, TuplePositionContent c) {
868-
access.getNameRef().getText().toInt() = c.getPosition()
869-
}
870-
871885
/** A value that represents a set of `Content`s. */
872886
abstract class ContentSet extends TContentSet {
873887
/** Gets a textual representation of this element. */
@@ -1103,6 +1117,10 @@ module RustDataFlow implements InputSig<Location> {
11031117
pathResolveToVariant(p, v)
11041118
}
11051119

1120+
/** Holds if `p` destructs an struct `s`. */
1121+
pragma[nomagic]
1122+
private predicate tupleStructDestruction(TupleStructPat p, Struct s) { pathResolveToStruct(p, s) }
1123+
11061124
/** Holds if `p` destructs an enum variant `v`. */
11071125
pragma[nomagic]
11081126
private predicate recordVariantDestruction(RecordPat p, Variant v) { pathResolveToVariant(p, v) }
@@ -1124,6 +1142,8 @@ module RustDataFlow implements InputSig<Location> {
11241142
|
11251143
tupleVariantDestruction(pat.getPat(), c.(VariantTupleFieldContent).getVariant(pos))
11261144
or
1145+
tupleStructDestruction(pat.getPat(), c.(StructTupleFieldContent).getStruct(pos))
1146+
or
11271147
VariantLib::tupleVariantCanonicalDestruction(pat.getPat(), c, pos)
11281148
)
11291149
or
@@ -1140,7 +1160,7 @@ module RustDataFlow implements InputSig<Location> {
11401160
recordVariantDestruction(pat.getPat(), c.(VariantRecordFieldContent).getVariant(field))
11411161
or
11421162
// Pattern destructs a struct.
1143-
structDestruction(pat.getPat(), c.(StructFieldContent).getStruct(field))
1163+
structDestruction(pat.getPat(), c.(StructRecordFieldContent).getStruct(field))
11441164
) and
11451165
node2.asPat() = pat.getFieldPat(field)
11461166
)
@@ -1149,11 +1169,9 @@ module RustDataFlow implements InputSig<Location> {
11491169
node1.asPat().(RefPatCfgNode).getPat() = node2.asPat()
11501170
or
11511171
exists(FieldExprCfgNode access |
1152-
// Read of a tuple entry
1153-
fieldTuplePositionContent(access, c) and
1154-
// TODO: Handle read of a struct field.
11551172
node1.asExpr() = access.getExpr() and
1156-
node2.asExpr() = access
1173+
node2.asExpr() = access and
1174+
access = c.(FieldContent).getAnAccess()
11571175
)
11581176
or
11591177
exists(IndexExprCfgNode arr |
@@ -1211,12 +1229,13 @@ module RustDataFlow implements InputSig<Location> {
12111229
pragma[nomagic]
12121230
private predicate structConstruction(RecordExpr re, Struct s) { pathResolveToStruct(re, s) }
12131231

1214-
private predicate tupleAssignment(Node node1, Node node2, TuplePositionContent c) {
1232+
pragma[nomagic]
1233+
private predicate fieldAssignment(Node node1, Node node2, FieldContent c) {
12151234
exists(AssignmentExprCfgNode assignment, FieldExprCfgNode access |
12161235
assignment.getLhs() = access and
1217-
fieldTuplePositionContent(access, c) and
12181236
node1.asExpr() = assignment.getRhs() and
1219-
node2.asExpr() = access.getExpr()
1237+
node2.asExpr() = access.getExpr() and
1238+
access = c.getAnAccess()
12201239
)
12211240
}
12221241

@@ -1238,7 +1257,7 @@ module RustDataFlow implements InputSig<Location> {
12381257
c.(VariantRecordFieldContent).getVariant(field))
12391258
or
12401259
// Expression is for a struct.
1241-
structConstruction(re.getRecordExpr(), c.(StructFieldContent).getStruct(field))
1260+
structConstruction(re.getRecordExpr(), c.(StructRecordFieldContent).getStruct(field))
12421261
) and
12431262
node1.asExpr() = re.getFieldExpr(field) and
12441263
node2.asExpr() = re
@@ -1256,7 +1275,7 @@ module RustDataFlow implements InputSig<Location> {
12561275
node2.asExpr().(ArrayListExprCfgNode).getAnExpr()
12571276
]
12581277
or
1259-
tupleAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), c)
1278+
fieldAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), c)
12601279
or
12611280
exists(AssignmentExprCfgNode assignment, IndexExprCfgNode index |
12621281
c instanceof ElementContent and
@@ -1292,7 +1311,7 @@ module RustDataFlow implements InputSig<Location> {
12921311
* in `x.f = newValue`.
12931312
*/
12941313
predicate clearsContent(Node n, ContentSet cs) {
1295-
tupleAssignment(_, n, cs.(SingletonContentSet).getContent())
1314+
fieldAssignment(_, n, cs.(SingletonContentSet).getContent())
12961315
or
12971316
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(Node::FlowSummaryNode).getSummaryNode(),
12981317
cs)
@@ -1598,12 +1617,12 @@ private module Cached {
15981617

15991618
cached
16001619
newtype TContent =
1601-
TVariantTupleFieldContent(Variant v, int pos) { exists(getVariantTupleField(v, pos)) } or
1620+
TVariantTupleFieldContent(Variant v, int pos) { exists(v.getTupleField(pos)) } or
16021621
// TODO: Remove once library types are extracted
16031622
TVariantLibTupleFieldContent(VariantLib::VariantLib v, int pos) {
16041623
VariantLib::variantLibPos(v, pos)
16051624
} or
1606-
TVariantRecordFieldContent(Variant v, string field) { exists(getVariantRecordField(v, field)) } or
1625+
TVariantRecordFieldContent(Variant v, string field) { exists(v.getRecordField(field)) } or
16071626
TElementContent() or
16081627
TTuplePositionContent(int pos) {
16091628
pos in [0 .. max([
@@ -1612,9 +1631,8 @@ private module Cached {
16121631
]
16131632
)]
16141633
} or
1615-
TStructFieldContent(Struct s, string field) {
1616-
field = s.getFieldList().(RecordFieldList).getAField().getName().getText()
1617-
} or
1634+
TStructTupleFieldContent(Struct s, int pos) { exists(s.getTupleField(pos)) } or
1635+
TStructRecordFieldContent(Struct s, string field) { exists(s.getRecordField(field)) } or
16181636
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
16191637
TReferenceContent()
16201638

rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ module Input implements InputSig<Location, RustDataFlow> {
8383
or
8484
exists(Struct s, string field |
8585
result = "Struct" and
86-
c = TStructFieldContent(s, field) and
86+
c = TStructRecordFieldContent(s, field) and
8787
// TODO: calculate in QL
8888
arg = s.getExtendedCanonicalPath() + "::" + field
8989
)

rust/ql/lib/codeql/rust/elements/internal/StructImpl.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* INTERNAL: Do not use.
55
*/
66

7+
private import rust
78
private import codeql.rust.elements.internal.generated.Struct
89

910
/**
@@ -20,5 +21,16 @@ module Impl {
2021
*/
2122
class Struct extends Generated::Struct {
2223
override string toString() { result = "struct " + this.getName().getText() }
24+
25+
/** Gets the record field named `name`, if any. */
26+
pragma[nomagic]
27+
RecordField getRecordField(string name) {
28+
result = this.getFieldList().(RecordFieldList).getAField() and
29+
result.getName().getText() = name
30+
}
31+
32+
/** Gets the `i`th tuple field, if any. */
33+
pragma[nomagic]
34+
TupleField getTupleField(int i) { result = this.getFieldList().(TupleFieldList).getField(i) }
2335
}
2436
}

0 commit comments

Comments
 (0)