@@ -12,6 +12,64 @@ private import codeql.rust.controlflow.ControlFlowGraph
12
12
private import codeql.rust.controlflow.CfgNodes
13
13
private import codeql.rust.dataflow.Ssa
14
14
15
+ private newtype TReturnKind = TNormalReturnKind ( )
16
+
17
+ /**
18
+ * A return kind. A return kind describes how a value can be returned from a
19
+ * callable.
20
+ *
21
+ * The only return kind is a "normal" return from a `return` statement or an
22
+ * expression body.
23
+ */
24
+ final class ReturnKind extends TNormalReturnKind {
25
+ string toString ( ) { result = "return" }
26
+ }
27
+
28
+ /**
29
+ * A callable. This includes callables from source code, as well as callables
30
+ * defined in library code.
31
+ */
32
+ final class DataFlowCallable extends TDataFlowCallable {
33
+ /**
34
+ * Gets the underlying CFG scope, if any.
35
+ */
36
+ CfgScope asCfgScope ( ) { this = TCfgScope ( result ) }
37
+
38
+ /** Gets a textual representation of this callable. */
39
+ string toString ( ) { result = this .asCfgScope ( ) .toString ( ) }
40
+
41
+ /** Gets the location of this callable. */
42
+ Location getLocation ( ) { result = this .asCfgScope ( ) .getLocation ( ) }
43
+ }
44
+
45
+ abstract class DataFlowCall extends TDataFlowCall {
46
+ /** Gets the enclosing callable. */
47
+ abstract DataFlowCallable getEnclosingCallable ( ) ;
48
+
49
+ /** Gets the underlying source code call, if any. */
50
+ abstract CallCfgNode asCall ( ) ;
51
+
52
+ abstract string toString ( ) ;
53
+
54
+ /** Gets the location of this call. */
55
+ abstract Location getLocation ( ) ;
56
+ }
57
+
58
+ final class NormalCall extends DataFlowCall , TNormalCall {
59
+ private CallCfgNode c ;
60
+
61
+ NormalCall ( ) { this = TNormalCall ( c ) }
62
+
63
+ /** Gets the underlying call in the CFG, if any. */
64
+ override CallCfgNode asCall ( ) { result = c }
65
+
66
+ override DataFlowCallable getEnclosingCallable ( ) { none ( ) }
67
+
68
+ override string toString ( ) { result = c .toString ( ) }
69
+
70
+ override Location getLocation ( ) { result = c .getLocation ( ) }
71
+ }
72
+
15
73
module Node {
16
74
/**
17
75
* An element, viewed as a node in a data flow graph. Either an expression
@@ -29,6 +87,12 @@ module Node {
29
87
*/
30
88
Expr asExpr ( ) { none ( ) }
31
89
90
+ /** Gets the enclosing callable. */
91
+ DataFlowCallable getEnclosingCallable ( ) { result = TCfgScope ( this .getCfgScope ( ) ) }
92
+
93
+ /** Do not call: use `getEnclosingCallable()` instead. */
94
+ abstract CfgScope getCfgScope ( ) ;
95
+
32
96
/**
33
97
* Gets the control flow node that corresponds to this data flow node.
34
98
*/
@@ -49,6 +113,8 @@ module Node {
49
113
final class NaNode extends Node {
50
114
NaNode ( ) { none ( ) }
51
115
116
+ override CfgScope getCfgScope ( ) { none ( ) }
117
+
52
118
override string toString ( ) { result = "N/A" }
53
119
54
120
override Location getLocation ( ) { none ( ) }
@@ -62,11 +128,13 @@ module Node {
62
128
* to multiple `ExprNode`s, just like it may correspond to multiple
63
129
* `ControlFlow::Node`s.
64
130
*/
65
- final class ExprNode extends Node , TExprNode {
131
+ class ExprNode extends Node , TExprNode {
66
132
ExprCfgNode n ;
67
133
68
134
ExprNode ( ) { this = TExprNode ( n ) }
69
135
136
+ override CfgScope getCfgScope ( ) { result = this .asExpr ( ) .getEnclosingCallable ( ) }
137
+
70
138
override Location getLocation ( ) { result = n .getExpr ( ) .getLocation ( ) }
71
139
72
140
override string toString ( ) { result = n .getExpr ( ) .toString ( ) }
@@ -85,6 +153,8 @@ module Node {
85
153
86
154
ParameterNode ( ) { this = TParameterNode ( parameter ) }
87
155
156
+ override CfgScope getCfgScope ( ) { result = parameter .getEnclosingCallable ( ) }
157
+
88
158
override Location getLocation ( ) { result = parameter .getLocation ( ) }
89
159
90
160
override string toString ( ) { result = parameter .toString ( ) }
@@ -105,6 +175,8 @@ module Node {
105
175
def = node .getDefinitionExt ( )
106
176
}
107
177
178
+ override CfgScope getCfgScope ( ) { result = def .getBasicBlock ( ) .getScope ( ) }
179
+
108
180
SsaImpl:: DefinitionExt getDefinitionExt ( ) { result = def }
109
181
110
182
/** Holds if this node should be hidden from path explanations. */
@@ -115,11 +187,25 @@ module Node {
115
187
override string toString ( ) { result = node .toString ( ) }
116
188
}
117
189
118
- final class ReturnNode extends NaNode {
119
- RustDataFlow:: ReturnKind getKind ( ) { none ( ) }
190
+ /** A data flow node that represents a value returned by a callable. */
191
+ final class ReturnNode extends ExprNode {
192
+ ReturnNode ( ) { this .getCfgNode ( ) .getASuccessor ( ) instanceof ExitCfgNode }
193
+
194
+ ReturnKind getKind ( ) { any ( ) }
195
+ }
196
+
197
+ /** A data-flow node that represents the output of a call. */
198
+ abstract class OutNode extends Node , ExprNode {
199
+ /** Gets the underlying call, where this node is a corresponding output of kind `kind`. */
200
+ abstract DataFlowCall getCall ( ) ;
120
201
}
121
202
122
- final class OutNode = NaNode ;
203
+ final private class ExprOutNode extends OutNode {
204
+ ExprOutNode ( ) { this .asExpr ( ) instanceof CallExpr }
205
+
206
+ /** Gets the underlying call CFG node that includes this out node. */
207
+ override DataFlowCall getCall ( ) { result .( NormalCall ) .asCall ( ) = this .getCfgNode ( ) }
208
+ }
123
209
124
210
/**
125
211
* A node associated with an object after an operation that might have
@@ -198,6 +284,12 @@ module LocalFlow {
198
284
}
199
285
}
200
286
287
+ class DataFlowCallableAlias = DataFlowCallable ;
288
+
289
+ class ReturnKindAlias = ReturnKind ;
290
+
291
+ class DataFlowCallAlias = DataFlowCall ;
292
+
201
293
module RustDataFlow implements InputSig< Location > {
202
294
/**
203
295
* An element, viewed as a node in a data flow graph. Either an expression
@@ -221,7 +313,7 @@ module RustDataFlow implements InputSig<Location> {
221
313
222
314
predicate isArgumentNode ( ArgumentNode n , DataFlowCall call , ArgumentPosition pos ) { none ( ) }
223
315
224
- DataFlowCallable nodeGetEnclosingCallable ( Node node ) { none ( ) }
316
+ DataFlowCallable nodeGetEnclosingCallable ( Node node ) { result = node . getEnclosingCallable ( ) }
225
317
226
318
DataFlowType getNodeType ( Node node ) { any ( ) }
227
319
@@ -232,26 +324,22 @@ module RustDataFlow implements InputSig<Location> {
232
324
/** Gets the node corresponding to `e`. */
233
325
Node exprNode ( DataFlowExpr e ) { result .getCfgNode ( ) = e }
234
326
235
- final class DataFlowCall extends TNormalCall {
236
- private CallExpr c ;
237
-
238
- DataFlowCall ( ) { this = TNormalCall ( c ) }
239
-
240
- DataFlowCallable getEnclosingCallable ( ) { none ( ) }
241
-
242
- string toString ( ) { result = c .toString ( ) }
243
-
244
- Location getLocation ( ) { result = c .getLocation ( ) }
245
- }
327
+ final class DataFlowCall = DataFlowCallAlias ;
246
328
247
- final class DataFlowCallable = CfgScope ;
329
+ final class DataFlowCallable = DataFlowCallableAlias ;
248
330
249
- final class ReturnKind = Void ;
331
+ final class ReturnKind = ReturnKindAlias ;
250
332
251
333
/** Gets a viable implementation of the target of the given `Call`. */
252
334
DataFlowCallable viableCallable ( DataFlowCall c ) { none ( ) }
253
335
254
- OutNode getAnOutNode ( DataFlowCall call , ReturnKind kind ) { none ( ) }
336
+ /**
337
+ * Gets a node that can read the value returned from `call` with return kind
338
+ * `kind`.
339
+ */
340
+ OutNode getAnOutNode ( DataFlowCall call , ReturnKind kind ) {
341
+ call = result .getCall ( ) and exists ( kind )
342
+ }
255
343
256
344
// NOTE: For now we use the type `Unit` and do not benefit from type
257
345
// information in the data flow analysis.
@@ -400,7 +488,7 @@ private module Cached {
400
488
TSsaNode ( SsaImpl:: DataFlowIntegration:: SsaNode node )
401
489
402
490
cached
403
- newtype TDataFlowCall = TNormalCall ( CallExpr c )
491
+ newtype TDataFlowCall = TNormalCall ( CallCfgNode c )
404
492
405
493
cached
406
494
newtype TOptionalContentSet =
@@ -410,6 +498,9 @@ private module Cached {
410
498
cached
411
499
class TContentSet = TAnyElementContent or TAnyContent ;
412
500
501
+ cached
502
+ newtype TDataFlowCallable = TCfgScope ( CfgScope scope )
503
+
413
504
/** This is the local flow predicate that is exposed. */
414
505
cached
415
506
predicate localFlowStepImpl ( Node:: Node nodeFrom , Node:: Node nodeTo ) {
0 commit comments