@@ -7,7 +7,9 @@ private import codeql.util.Unit
7
7
private import codeql.dataflow.DataFlow
8
8
private import codeql.dataflow.internal.DataFlowImpl
9
9
private import rust
10
+ private import SsaImpl as SsaImpl
10
11
private import codeql.rust.controlflow.ControlFlowGraph
12
+ private import codeql.rust.controlflow.CfgNodes
11
13
private import codeql.rust.dataflow.Ssa
12
14
13
15
module Node {
@@ -52,22 +54,67 @@ module Node {
52
54
override Location getLocation ( ) { none ( ) }
53
55
}
54
56
57
+ /**
58
+ * A node in the data flow graph that corresponds to an expression in the
59
+ * AST.
60
+ *
61
+ * Note that because of control-flow splitting, one `Expr` may correspond
62
+ * to multiple `ExprNode`s, just like it may correspond to multiple
63
+ * `ControlFlow::Node`s.
64
+ */
65
+ final class ExprNode extends Node , TExprNode {
66
+ ExprCfgNode n ;
67
+
68
+ ExprNode ( ) { this = TExprNode ( n ) }
69
+
70
+ override Location getLocation ( ) { result = n .getExpr ( ) .getLocation ( ) }
71
+
72
+ override string toString ( ) { result = n .getExpr ( ) .toString ( ) }
73
+
74
+ override Expr asExpr ( ) { result = n .getExpr ( ) }
75
+
76
+ override CfgNode getCfgNode ( ) { result = n }
77
+ }
78
+
55
79
/**
56
80
* The value of a parameter at function entry, viewed as a node in a data
57
81
* flow graph.
58
82
*/
59
- final class ParameterNode extends Node {
60
- Param param ;
83
+ final class ParameterNode extends Node , TParameterNode {
84
+ Param parameter ;
85
+
86
+ ParameterNode ( ) { this = TParameterNode ( parameter ) }
61
87
62
- ParameterNode ( ) { this = TSourceParameterNode ( param ) }
88
+ override Location getLocation ( ) { result = parameter . getLocation ( ) }
63
89
64
- override Location getLocation ( ) { result = param . getLocation ( ) }
90
+ override string toString ( ) { result = parameter . toString ( ) }
65
91
66
- override string toString ( ) { result = param .toString ( ) }
92
+ /** Gets the parameter in the AST that this node corresponds to. */
93
+ Param getParameter ( ) { result = parameter }
67
94
}
68
95
69
96
final class ArgumentNode = NaNode ;
70
97
98
+ /** An SSA node. */
99
+ class SsaNode extends Node , TSsaNode {
100
+ SsaImpl:: DataFlowIntegration:: SsaNode node ;
101
+ SsaImpl:: DefinitionExt def ;
102
+
103
+ SsaNode ( ) {
104
+ this = TSsaNode ( node ) and
105
+ def = node .getDefinitionExt ( )
106
+ }
107
+
108
+ SsaImpl:: DefinitionExt getDefinitionExt ( ) { result = def }
109
+
110
+ /** Holds if this node should be hidden from path explanations. */
111
+ abstract predicate isHidden ( ) ;
112
+
113
+ override Location getLocation ( ) { result = node .getLocation ( ) }
114
+
115
+ override string toString ( ) { result = node .toString ( ) }
116
+ }
117
+
71
118
final class ReturnNode extends NaNode {
72
119
RustDataFlow:: ReturnKind getKind ( ) { none ( ) }
73
120
}
@@ -93,6 +140,64 @@ module Node {
93
140
final class CastNode = NaNode ;
94
141
}
95
142
143
+ final class Node = Node:: Node ;
144
+
145
+ /** Provides logic related to SSA. */
146
+ module SsaFlow {
147
+ private module Impl = SsaImpl:: DataFlowIntegration;
148
+
149
+ private Node:: ParameterNode toParameterNode ( Param p ) { result = TParameterNode ( p ) }
150
+
151
+ /** Converts a control flow node into an SSA control flow node. */
152
+ Impl:: Node asNode ( Node n ) {
153
+ n = TSsaNode ( result )
154
+ or
155
+ result .( Impl:: ExprNode ) .getExpr ( ) = n .( Node:: ExprNode ) .getCfgNode ( )
156
+ or
157
+ n = toParameterNode ( result .( Impl:: ParameterNode ) .getParameter ( ) )
158
+ }
159
+
160
+ predicate localFlowStep ( SsaImpl:: DefinitionExt def , Node nodeFrom , Node nodeTo , boolean isUseStep ) {
161
+ Impl:: localFlowStep ( def , asNode ( nodeFrom ) , asNode ( nodeTo ) , isUseStep )
162
+ }
163
+
164
+ predicate localMustFlowStep ( SsaImpl:: DefinitionExt def , Node nodeFrom , Node nodeTo ) {
165
+ Impl:: localMustFlowStep ( def , asNode ( nodeFrom ) , asNode ( nodeTo ) )
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Holds for expressions `e` that evaluate to the value of any last (in
171
+ * evaluation order) subexpressions within it. E.g., expressions that propagate
172
+ * a values from a subexpression.
173
+ *
174
+ * For instance, the predicate holds for if expressions as `if b { e1 } else {
175
+ * e2 }` evalates to the value of one of the subexpressions `e1` or `e2`.
176
+ */
177
+ private predicate propagatesValue ( Expr e ) {
178
+ e instanceof IfExpr or
179
+ e instanceof LoopExpr or
180
+ e instanceof ReturnExpr or
181
+ e instanceof BreakExpr or
182
+ e .( BlockExpr ) .getStmtList ( ) .hasTailExpr ( ) or
183
+ e instanceof MatchExpr
184
+ }
185
+
186
+ /**
187
+ * Gets a node that may execute last in `n`, and which, when it executes last,
188
+ * will be the value of `n`.
189
+ */
190
+ private ExprCfgNode getALastEvalNode ( ExprCfgNode n ) {
191
+ propagatesValue ( n .getExpr ( ) ) and result .getASuccessor ( ) = n
192
+ }
193
+
194
+ module LocalFlow {
195
+ pragma [ nomagic]
196
+ predicate localFlowStepCommon ( Node nodeFrom , Node nodeTo ) {
197
+ nodeFrom .getCfgNode ( ) = getALastEvalNode ( nodeTo .getCfgNode ( ) )
198
+ }
199
+ }
200
+
96
201
module RustDataFlow implements InputSig< Location > {
97
202
/**
98
203
* An element, viewed as a node in a data flow graph. Either an expression
@@ -122,10 +227,10 @@ module RustDataFlow implements InputSig<Location> {
122
227
123
228
predicate nodeIsHidden ( Node node ) { none ( ) }
124
229
125
- class DataFlowExpr = Void ;
230
+ class DataFlowExpr = ExprCfgNode ;
126
231
127
232
/** Gets the node corresponding to `e`. */
128
- Node exprNode ( DataFlowExpr e ) { none ( ) }
233
+ Node exprNode ( DataFlowExpr e ) { result . getCfgNode ( ) = e }
129
234
130
235
final class DataFlowCall extends TNormalCall {
131
236
private CallExpr c ;
@@ -191,7 +296,7 @@ module RustDataFlow implements InputSig<Location> {
191
296
* Holds if there is a simple local flow step from `node1` to `node2`. These
192
297
* are the value-preserving intra-callable flow steps.
193
298
*/
194
- predicate simpleLocalFlowStep ( Node node1 , Node node2 , string model ) { none ( ) }
299
+ predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo , string model ) { none ( ) }
195
300
196
301
/**
197
302
* Holds if data can flow from `node1` to `node2` through a non-local step
@@ -256,7 +361,9 @@ module RustDataFlow implements InputSig<Location> {
256
361
* `node2` must be visited along a flow path, then any type known for `node2`
257
362
* must also apply to `node1`.
258
363
*/
259
- predicate localMustFlowStep ( Node node1 , Node node2 ) { none ( ) }
364
+ predicate localMustFlowStep ( Node node1 , Node node2 ) {
365
+ SsaFlow:: localMustFlowStep ( _, node1 , node2 )
366
+ }
260
367
261
368
class LambdaCallKind = Void ;
262
369
@@ -267,7 +374,7 @@ module RustDataFlow implements InputSig<Location> {
267
374
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
268
375
predicate lambdaCall ( DataFlowCall call , LambdaCallKind kind , Node receiver ) { none ( ) }
269
376
270
- /** Extra data- flow steps needed for lambda flow analysis. */
377
+ /** Extra data flow steps needed for lambda flow analysis. */
271
378
predicate additionalLambdaFlowStep ( Node nodeFrom , Node nodeTo , boolean preservesValue ) { none ( ) }
272
379
273
380
predicate knownSourceModel ( Node source , string model ) { none ( ) }
@@ -286,8 +393,9 @@ cached
286
393
private module Cached {
287
394
cached
288
395
newtype TNode =
289
- TExprNode ( CfgNode n , Expr e ) { n .getAstNode ( ) = e } or
290
- TSourceParameterNode ( Param param )
396
+ TExprNode ( ExprCfgNode n ) or
397
+ TParameterNode ( Param p ) or
398
+ TSsaNode ( SsaImpl:: DataFlowIntegration:: SsaNode node )
291
399
292
400
cached
293
401
newtype TDataFlowCall = TNormalCall ( CallExpr c )
@@ -302,7 +410,11 @@ private module Cached {
302
410
303
411
/** This is the local flow predicate that is exposed. */
304
412
cached
305
- predicate localFlowStepImpl ( Node:: Node nodeFrom , Node:: Node nodeTo ) { none ( ) }
413
+ predicate localFlowStepImpl ( Node:: Node nodeFrom , Node:: Node nodeTo ) {
414
+ LocalFlow:: localFlowStepCommon ( nodeFrom , nodeTo )
415
+ or
416
+ SsaFlow:: localFlowStep ( _, nodeFrom , nodeTo , _)
417
+ }
306
418
}
307
419
308
420
import Cached
0 commit comments