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