Skip to content

Commit 72346cc

Browse files
authored
Merge pull request #19004 from paldepind/rust-data-flow-split
Rust: Extract data flow node and content into separate files
2 parents 996bc47 + 5a3bf90 commit 72346cc

File tree

14 files changed

+807
-762
lines changed

14 files changed

+807
-762
lines changed

rust/ql/lib/codeql/rust/dataflow/DataFlow.qll

+18-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
private import rust
77
private import codeql.dataflow.DataFlow
88
private import internal.DataFlowImpl as DataFlowImpl
9-
private import DataFlowImpl::Node as Node
9+
private import internal.Node as Node
10+
private import internal.Content as Content
1011

1112
/**
1213
* Provides classes for performing local (intra-procedural) and global
@@ -23,9 +24,23 @@ module DataFlow {
2324

2425
final class PostUpdateNode = Node::PostUpdateNodePublic;
2526

26-
final class Content = DataFlowImpl::Content;
27+
final class Content = Content::Content;
2728

28-
final class ContentSet = DataFlowImpl::ContentSet;
29+
final class FieldContent = Content::FieldContent;
30+
31+
final class TuplePositionContent = Content::TuplePositionContent;
32+
33+
final class TupleFieldContent = Content::TupleFieldContent;
34+
35+
final class RecordFieldContent = Content::RecordFieldContent;
36+
37+
final class ReferenceContent = Content::ReferenceContent;
38+
39+
final class ElementContent = Content::ElementContent;
40+
41+
final class FutureContent = Content::FutureContent;
42+
43+
final class ContentSet = Content::ContentSet;
2944

3045
/**
3146
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
/**
2+
* Provides the `Content` class and subclasses thereof.
3+
*/
4+
5+
private import rust
6+
private import codeql.rust.controlflow.CfgNodes
7+
private import DataFlowImpl
8+
9+
/**
10+
* A path to a value contained in an object. For example a field name of a struct.
11+
*/
12+
abstract class Content extends TContent {
13+
/** Gets a textual representation of this content. */
14+
abstract string toString();
15+
16+
/** Gets the location of this content. */
17+
abstract Location getLocation();
18+
}
19+
20+
/** A field belonging to either a variant or a struct. */
21+
abstract class FieldContent extends Content {
22+
/** Gets an access to this field. */
23+
pragma[nomagic]
24+
abstract FieldExprCfgNode getAnAccess();
25+
}
26+
27+
/** A tuple field belonging to either a variant or a struct. */
28+
class TupleFieldContent extends FieldContent, TTupleFieldContent {
29+
private TupleField field;
30+
31+
TupleFieldContent() { this = TTupleFieldContent(field) }
32+
33+
/** Holds if this field belongs to an enum variant. */
34+
predicate isVariantField(Variant v, int pos) { field.isVariantField(v, pos) }
35+
36+
/** Holds if this field belongs to a struct. */
37+
predicate isStructField(Struct s, int pos) { field.isStructField(s, pos) }
38+
39+
override FieldExprCfgNode getAnAccess() { field = result.getFieldExpr().getTupleField() }
40+
41+
final override string toString() {
42+
exists(Variant v, int pos, string vname |
43+
this.isVariantField(v, pos) and
44+
vname = v.getName().getText() and
45+
// only print indices when the arity is > 1
46+
if exists(v.getTupleField(1)) then result = vname + "(" + pos + ")" else result = vname
47+
)
48+
or
49+
exists(Struct s, int pos, string sname |
50+
this.isStructField(s, pos) and
51+
sname = s.getName().getText() and
52+
// only print indices when the arity is > 1
53+
if exists(s.getTupleField(1)) then result = sname + "(" + pos + ")" else result = sname
54+
)
55+
}
56+
57+
final override Location getLocation() { result = field.getLocation() }
58+
}
59+
60+
/** A record field belonging to either a variant or a struct. */
61+
class RecordFieldContent extends FieldContent, TRecordFieldContent {
62+
private RecordField field;
63+
64+
RecordFieldContent() { this = TRecordFieldContent(field) }
65+
66+
/** Holds if this field belongs to an enum variant. */
67+
predicate isVariantField(Variant v, string name) { field.isVariantField(v, name) }
68+
69+
/** Holds if this field belongs to a struct. */
70+
predicate isStructField(Struct s, string name) { field.isStructField(s, name) }
71+
72+
override FieldExprCfgNode getAnAccess() { field = result.getFieldExpr().getRecordField() }
73+
74+
final override string toString() {
75+
exists(Variant v, string name, string vname |
76+
this.isVariantField(v, name) and
77+
vname = v.getName().getText() and
78+
// only print field when the arity is > 1
79+
if strictcount(v.getRecordField(_)) > 1 then result = vname + "." + name else result = vname
80+
)
81+
or
82+
exists(Struct s, string name, string sname |
83+
this.isStructField(s, name) and
84+
sname = s.getName().getText() and
85+
// only print field when the arity is > 1
86+
if strictcount(s.getRecordField(_)) > 1 then result = sname + "." + name else result = sname
87+
)
88+
}
89+
90+
final override Location getLocation() { result = field.getLocation() }
91+
}
92+
93+
/** A captured variable. */
94+
final class CapturedVariableContent extends Content, TCapturedVariableContent {
95+
private Variable v;
96+
97+
CapturedVariableContent() { this = TCapturedVariableContent(v) }
98+
99+
/** Gets the captured variable. */
100+
Variable getVariable() { result = v }
101+
102+
override string toString() { result = "captured " + v }
103+
104+
override Location getLocation() { result = v.getLocation() }
105+
}
106+
107+
/** A value referred to by a reference. */
108+
final class ReferenceContent extends Content, TReferenceContent {
109+
override string toString() { result = "&ref" }
110+
111+
override Location getLocation() { result instanceof EmptyLocation }
112+
}
113+
114+
/**
115+
* An element in a collection where we do not track the specific collection
116+
* type nor the placement of the element in the collection. Therefore the
117+
* collection should be one where the elements are reasonably homogeneous,
118+
* i.e., if one is tainted all elements are considered tainted.
119+
*
120+
* Examples include the elements of a set, array, vector, or stack.
121+
*/
122+
final class ElementContent extends Content, TElementContent {
123+
override string toString() { result = "element" }
124+
125+
override Location getLocation() { result instanceof EmptyLocation }
126+
}
127+
128+
/**
129+
* A value that a future resolves to.
130+
*/
131+
final class FutureContent extends Content, TFutureContent {
132+
override string toString() { result = "future" }
133+
134+
override Location getLocation() { result instanceof EmptyLocation }
135+
}
136+
137+
/**
138+
* Content stored at a position in a tuple.
139+
*
140+
* NOTE: Unlike `struct`s and `enum`s tuples are structural and not nominal,
141+
* hence we don't store a canonical path for them.
142+
*/
143+
final class TuplePositionContent extends FieldContent, TTuplePositionContent {
144+
private int pos;
145+
146+
TuplePositionContent() { this = TTuplePositionContent(pos) }
147+
148+
/** Gets the index of this tuple position. */
149+
int getPosition() { result = pos }
150+
151+
override FieldExprCfgNode getAnAccess() {
152+
// TODO: limit to tuple types
153+
result.getNameRef().getText().toInt() = pos
154+
}
155+
156+
override string toString() { result = "tuple." + pos.toString() }
157+
158+
override Location getLocation() { result instanceof EmptyLocation }
159+
}
160+
161+
/**
162+
* A content for the index of an argument to at function call.
163+
*
164+
* Used by the model generator to create flow summaries for higher-order
165+
* functions.
166+
*/
167+
final class FunctionCallArgumentContent extends Content, TFunctionCallArgumentContent {
168+
private int pos;
169+
170+
FunctionCallArgumentContent() { this = TFunctionCallArgumentContent(pos) }
171+
172+
int getPosition() { result = pos }
173+
174+
override string toString() { result = "function argument at " + pos }
175+
176+
override Location getLocation() { result instanceof EmptyLocation }
177+
}
178+
179+
/**
180+
* A content for the return value of function call.
181+
*
182+
* Used by the model generator to create flow summaries for higher-order
183+
* functions.
184+
*/
185+
final class FunctionCallReturnContent extends Content, TFunctionCallReturnContent {
186+
override string toString() { result = "function return" }
187+
188+
override Location getLocation() { result instanceof EmptyLocation }
189+
}
190+
191+
/** A value that represents a set of `Content`s. */
192+
abstract class ContentSet extends TContentSet {
193+
/** Gets a textual representation of this element. */
194+
abstract string toString();
195+
196+
/** Gets a content that may be stored into when storing into this set. */
197+
abstract Content getAStoreContent();
198+
199+
/** Gets a content that may be read from when reading from this set. */
200+
abstract Content getAReadContent();
201+
}
202+
203+
final class SingletonContentSet extends ContentSet, TSingletonContentSet {
204+
private Content c;
205+
206+
SingletonContentSet() { this = TSingletonContentSet(c) }
207+
208+
Content getContent() { result = c }
209+
210+
override string toString() { result = c.toString() }
211+
212+
override Content getAStoreContent() { result = c }
213+
214+
override Content getAReadContent() { result = c }
215+
}
216+
217+
private import codeql.rust.internal.CachedStages
218+
219+
cached
220+
newtype TContent =
221+
TTupleFieldContent(TupleField field) { Stages::DataFlowStage::ref() } or
222+
TRecordFieldContent(RecordField field) or
223+
// TODO: Remove once library types are extracted
224+
TVariantInLibTupleFieldContent(VariantInLib::VariantInLib v, int pos) { pos = v.getAPosition() } or
225+
TElementContent() or
226+
TFutureContent() or
227+
TTuplePositionContent(int pos) {
228+
pos in [0 .. max([
229+
any(TuplePat pat).getNumberOfFields(),
230+
any(FieldExpr access).getNameRef().getText().toInt()
231+
]
232+
)]
233+
} or
234+
TFunctionCallReturnContent() or
235+
TFunctionCallArgumentContent(int pos) {
236+
pos in [0 .. any(CallExpr c).getArgList().getNumberOfArgs() - 1]
237+
} or
238+
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
239+
TReferenceContent()

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

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import codeql.rust.dataflow.DataFlow::DataFlow as DataFlow
22
private import rust
33
private import codeql.rust.dataflow.internal.DataFlowImpl
4+
private import codeql.rust.dataflow.internal.Node as Node
45
private import codeql.rust.dataflow.internal.TaintTrackingImpl
56
private import codeql.dataflow.internal.DataFlowImplConsistency
67

0 commit comments

Comments
 (0)