@@ -4,11 +4,9 @@ private import DataFlowPublic
4
4
//--------
5
5
// Data flow graph
6
6
//--------
7
-
8
7
//--------
9
8
// Nodes
10
9
//--------
11
-
12
10
/**
13
11
* A node associated with an object after an operation that might have
14
12
* changed its state.
@@ -40,7 +38,8 @@ module EssaFlow {
40
38
// `x = f(42)`
41
39
// nodeFrom is `f(42)`, cfg node
42
40
// nodeTo is `x`, essa var
43
- nodeFrom .( CfgNode ) .getNode ( ) = nodeTo .( EssaNode ) .getVar ( ) .getDefinition ( ) .( AssignmentDefinition ) .getValue ( )
41
+ nodeFrom .( CfgNode ) .getNode ( ) =
42
+ nodeTo .( EssaNode ) .getVar ( ) .getDefinition ( ) .( AssignmentDefinition ) .getValue ( )
44
43
or
45
44
// With definition
46
45
// `with f(42) as x:`
@@ -49,7 +48,7 @@ module EssaFlow {
49
48
exists ( With with , ControlFlowNode contextManager , ControlFlowNode var |
50
49
nodeFrom .( CfgNode ) .getNode ( ) = contextManager and
51
50
nodeTo .( EssaNode ) .getVar ( ) .getDefinition ( ) .( WithDefinition ) .getDefiningNode ( ) = var and
52
- // see `with_flow`
51
+ // see `with_flow` in `python/ql/src/semmle/python/dataflow/Implementation.qll`
53
52
with .getContextExpr ( ) = contextManager .getNode ( ) and
54
53
with .getOptionalVars ( ) = var .getNode ( ) and
55
54
contextManager .strictlyDominates ( var )
@@ -83,7 +82,6 @@ module EssaFlow {
83
82
//--------
84
83
// Local flow
85
84
//--------
86
-
87
85
/**
88
86
* This is the local flow predicate that is used as a building block in global
89
87
* data flow. It is a strict subset of the `localFlowStep` predicate, as it
@@ -99,48 +97,35 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
99
97
//--------
100
98
// Global flow
101
99
//--------
102
-
103
100
/** Represents a callable */
104
101
class DataFlowCallable = CallableValue ;
105
102
106
103
/** Represents a call to a callable */
107
104
class DataFlowCall extends CallNode {
108
105
DataFlowCallable callable ;
109
106
110
- DataFlowCall ( ) {
111
- this = callable .getACall ( )
112
- }
107
+ DataFlowCall ( ) { this = callable .getACall ( ) }
113
108
114
109
/** Get the callable to which this call goes. */
115
110
DataFlowCallable getCallable ( ) { result = callable }
116
111
117
112
/** Gets the enclosing callable of this call. */
118
- DataFlowCallable getEnclosingCallable ( ) {
119
- result .getScope ( ) = this .getNode ( ) .getScope ( )
120
- }
113
+ DataFlowCallable getEnclosingCallable ( ) { result .getScope ( ) = this .getNode ( ) .getScope ( ) }
121
114
}
122
115
123
116
/** A data flow node that represents a call argument. */
124
117
class ArgumentNode extends CfgNode {
125
- ArgumentNode ( ) {
126
- exists ( DataFlowCall call , int pos |
127
- node = call .getArg ( pos )
128
- )
129
- }
118
+ ArgumentNode ( ) { exists ( DataFlowCall call , int pos | node = call .getArg ( pos ) ) }
130
119
131
- /** Holds if this argument occurs at the given position in the given call. */
132
- predicate argumentOf ( DataFlowCall call , int pos ) {
133
- node = call .getArg ( pos )
134
- }
120
+ /** Holds if this argument occurs at the given position in the given call. */
121
+ predicate argumentOf ( DataFlowCall call , int pos ) { node = call .getArg ( pos ) }
135
122
136
- /** Gets the call in which this node is an argument. */
123
+ /** Gets the call in which this node is an argument. */
137
124
final DataFlowCall getCall ( ) { this .argumentOf ( result , _) }
138
125
}
139
126
140
127
/** Gets a viable run-time target for the call `call`. */
141
- DataFlowCallable viableCallable ( DataFlowCall call ) {
142
- result = call .getCallable ( )
143
- }
128
+ DataFlowCallable viableCallable ( DataFlowCall call ) { result = call .getCallable ( ) }
144
129
145
130
private newtype TReturnKind = TNormalReturnKind ( )
146
131
@@ -157,49 +142,41 @@ class ReturnKind extends TReturnKind {
157
142
class ReturnNode extends CfgNode {
158
143
Return ret ;
159
144
160
- // See `TaintTrackingImplementation::returnFlowStep`
161
- ReturnNode ( ) {
162
- node = ret .getValue ( ) .getAFlowNode ( )
163
- }
145
+ // See `TaintTrackingImplementation::returnFlowStep`
146
+ ReturnNode ( ) { node = ret .getValue ( ) .getAFlowNode ( ) }
164
147
165
- /** Gets the kind of this return node. */
166
- ReturnKind getKind ( ) { result = TNormalReturnKind ( ) }
148
+ /** Gets the kind of this return node. */
149
+ ReturnKind getKind ( ) { any ( ) }
167
150
168
- override DataFlowCallable getEnclosingCallable ( ) {
151
+ override DataFlowCallable getEnclosingCallable ( ) {
169
152
result .getScope ( ) .getAStmt ( ) = ret // TODO: check nested function definitions
170
153
}
171
154
}
172
155
173
156
/** A data flow node that represents the output of a call. */
174
157
class OutNode extends CfgNode {
175
158
OutNode ( ) { node instanceof CallNode }
176
-
177
- /** Gets the underlying call, where this node is a corresponding output of kind `kind`. */
178
- cached
179
- DataFlowCall getCall ( ReturnKind kind ) {
180
- kind = TNormalReturnKind ( ) and
181
- result = node
182
- }
183
159
}
184
160
185
161
/**
186
162
* Gets a node that can read the value returned from `call` with return kind
187
163
* `kind`.
188
164
*/
189
- OutNode getAnOutNode ( DataFlowCall call , ReturnKind kind ) { call = result .getCall ( kind ) }
165
+ OutNode getAnOutNode ( DataFlowCall call , ReturnKind kind ) {
166
+ call = result .getNode ( ) and
167
+ kind = TNormalReturnKind ( )
168
+ }
190
169
191
170
//--------
192
171
// Type pruning
193
172
//--------
194
-
195
- newtype TDataFlowType =
196
- TStringFlow ( )
173
+ newtype TDataFlowType = TAnyFlow ( )
197
174
198
175
class DataFlowType extends TDataFlowType {
199
176
/**
200
177
* Gets a string representation of the data flow type.
201
178
*/
202
- string toString ( ) { result = "DataFlowType" }
179
+ string toString ( ) { result = "DataFlowType" }
203
180
}
204
181
205
182
/** A node that performs a type cast. */
@@ -212,22 +189,19 @@ class CastNode extends Node {
212
189
* a node of type `t1` to a node of type `t2`.
213
190
*/
214
191
pragma [ inline]
215
- predicate compatibleTypes ( DataFlowType t1 , DataFlowType t2 ) {
216
- any ( )
217
- }
192
+ predicate compatibleTypes ( DataFlowType t1 , DataFlowType t2 ) { any ( ) }
218
193
219
194
/**
220
195
* Gets the type of `node`.
221
196
*/
222
- DataFlowType getNodeType ( Node node ) { result = TStringFlow ( ) }
197
+ DataFlowType getNodeType ( Node node ) { result = TAnyFlow ( ) }
223
198
224
199
/** Gets a string representation of a type returned by `getErasedRepr`. */
225
200
string ppReprType ( DataFlowType t ) { none ( ) }
226
201
227
202
//--------
228
203
// Extra flow
229
204
//--------
230
-
231
205
/**
232
206
* Holds if `pred` can flow to `succ`, by jumping from one callable to
233
207
* another. Additional steps specified by the configuration are *not*
@@ -247,68 +221,52 @@ predicate jumpStep(Node pred, Node succ) {
247
221
//--------
248
222
// Field flow
249
223
//--------
250
-
251
224
/**
252
225
* Holds if data can flow from `node1` to `node2` via an assignment to
253
226
* content `c`.
254
227
*/
255
- predicate storeStep ( Node node1 , Content c , Node node2 ) {
256
- none ( )
257
- }
228
+ predicate storeStep ( Node node1 , Content c , Node node2 ) { none ( ) }
258
229
259
230
/**
260
231
* Holds if data can flow from `node1` to `node2` via a read of content `c`.
261
232
*/
262
- predicate readStep ( Node node1 , Content c , Node node2 ) {
263
- none ( )
264
- }
233
+ predicate readStep ( Node node1 , Content c , Node node2 ) { none ( ) }
265
234
266
235
/**
267
236
* Holds if values stored inside content `c` are cleared at node `n`. For example,
268
237
* any value stored inside `f` is cleared at the pre-update node associated with `x`
269
238
* in `x.f = newValue`.
270
239
*/
271
240
cached
272
- predicate clearsContent ( Node n , Content c ) {
273
- none ( )
274
- }
241
+ predicate clearsContent ( Node n , Content c ) { none ( ) }
275
242
276
243
//--------
277
244
// Fancy context-sensitive guards
278
245
//--------
279
-
280
246
/**
281
247
* Holds if the node `n` is unreachable when the call context is `call`.
282
248
*/
283
- predicate isUnreachableInCall ( Node n , DataFlowCall call ) {
284
- none ( )
285
- }
249
+ predicate isUnreachableInCall ( Node n , DataFlowCall call ) { none ( ) }
286
250
287
251
//--------
288
252
// Virtual dispatch with call context
289
253
//--------
290
-
291
254
/**
292
255
* Gets a viable dispatch target of `call` in the context `ctx`. This is
293
256
* restricted to those `call`s for which a context might make a difference.
294
257
*/
295
- DataFlowCallable viableImplInCallContext ( DataFlowCall call , DataFlowCall ctx ) {
296
- none ( )
297
- }
258
+ DataFlowCallable viableImplInCallContext ( DataFlowCall call , DataFlowCall ctx ) { none ( ) }
298
259
299
260
/**
300
261
* Holds if the set of viable implementations that can be called by `call`
301
262
* might be improved by knowing the call context. This is the case if the qualifier accesses a parameter of
302
263
* the enclosing callable `c` (including the implicit `this` parameter).
303
264
*/
304
- predicate mayBenefitFromCallContext ( DataFlowCall call , DataFlowCallable c ) {
305
- none ( )
306
- }
265
+ predicate mayBenefitFromCallContext ( DataFlowCall call , DataFlowCallable c ) { none ( ) }
307
266
308
267
//--------
309
268
// Misc
310
269
//--------
311
-
312
270
/**
313
271
* Holds if `n` does not require a `PostUpdateNode` as it either cannot be
314
272
* modified or its modification cannot be observed, for example if it is a
0 commit comments