@@ -137,22 +137,6 @@ module LocalFlow {
137
137
nodeTo = getSelfParameterDefNode ( nodeFrom .( SelfParameterNodeImpl ) .getMethod ( ) )
138
138
}
139
139
140
- /**
141
- * Holds if `nodeFrom -> nodeTo` is a step from a parameter to a capture entry node for
142
- * that parameter.
143
- *
144
- * This is intended to recover from flow not currently recognised by ordinary capture flow.
145
- */
146
- predicate localFlowSsaParamCaptureInput ( ParameterNodeImpl nodeFrom , Node nodeTo ) {
147
- exists ( Ssa:: CapturedEntryDefinition def |
148
- nodeTo .( SsaDefinitionExtNode ) .getDefinitionExt ( ) = def
149
- |
150
- nodeFrom .getParameter ( ) .( NamedParameter ) .getVariable ( ) = def .getSourceVariable ( )
151
- or
152
- nodeFrom .( SelfParameterNode ) .getSelfVariable ( ) = def .getSourceVariable ( )
153
- )
154
- }
155
-
156
140
/**
157
141
* Holds if there is a local use-use flow step from `nodeFrom` to `nodeTo`
158
142
* involving SSA definition `def`.
@@ -285,6 +269,53 @@ predicate isNonConstantExpr(CfgNodes::ExprCfgNode n) {
285
269
not n .getExpr ( ) instanceof ConstantAccess
286
270
}
287
271
272
+ /** Provides logic related to captured variables. */
273
+ module VariableCapture {
274
+ class CapturedVariable extends LocalVariable {
275
+ CapturedVariable ( ) { this .isCaptured ( ) }
276
+
277
+ CfgScope getCfgScope ( ) {
278
+ exists ( Scope scope | scope = this .getDeclaringScope ( ) |
279
+ result = scope
280
+ or
281
+ result = scope .( ModuleBase ) .getCfgScope ( )
282
+ )
283
+ }
284
+ }
285
+
286
+ class CapturedSsaDefinitionExt extends SsaImpl:: DefinitionExt {
287
+ CapturedSsaDefinitionExt ( ) { this .getSourceVariable ( ) instanceof CapturedVariable }
288
+ }
289
+
290
+ /**
291
+ * Holds if there is control-flow insensitive data-flow from `node1` to `node2`
292
+ * involving a captured variable. Only used in type tracking.
293
+ */
294
+ predicate flowInsensitiveStep ( Node node1 , Node node2 ) {
295
+ exists ( CapturedSsaDefinitionExt def , CapturedVariable v |
296
+ // From an assignment or implicit initialization of a captured variable to its flow-insensitive node
297
+ def = node1 .( SsaDefinitionExtNode ) .getDefinitionExt ( ) and
298
+ def .getSourceVariable ( ) = v and
299
+ (
300
+ def instanceof Ssa:: WriteDefinition
301
+ or
302
+ def instanceof Ssa:: SelfDefinition
303
+ ) and
304
+ node2 .( CapturedVariableNode ) .getVariable ( ) = v
305
+ or
306
+ // From a captured variable node to its flow-sensitive capture nodes
307
+ node1 .( CapturedVariableNode ) .getVariable ( ) = v and
308
+ def = node2 .( SsaDefinitionExtNode ) .getDefinitionExt ( ) and
309
+ def .getSourceVariable ( ) = v and
310
+ (
311
+ def instanceof Ssa:: CapturedCallDefinition
312
+ or
313
+ def instanceof Ssa:: CapturedEntryDefinition
314
+ )
315
+ )
316
+ }
317
+ }
318
+
288
319
/** A collection of cached types and predicates to be evaluated in the same stage. */
289
320
cached
290
321
private module Cached {
@@ -296,6 +327,7 @@ private module Cached {
296
327
TExprNode ( CfgNodes:: ExprCfgNode n ) { TaintTrackingPrivate:: forceCachingInSameStage ( ) } or
297
328
TReturningNode ( CfgNodes:: ReturningCfgNode n ) or
298
329
TSsaDefinitionExtNode ( SsaImpl:: DefinitionExt def ) or
330
+ TCapturedVariableNode ( VariableCapture:: CapturedVariable v ) or
299
331
TNormalParameterNode ( Parameter p ) {
300
332
p instanceof SimpleParameter or
301
333
p instanceof OptionalParameter or
@@ -389,6 +421,8 @@ private module Cached {
389
421
LocalFlow:: localFlowSsaInputFromRead ( exprFrom , _, nodeTo ) and
390
422
exprFrom = [ nodeFrom .asExpr ( ) , nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) ]
391
423
)
424
+ or
425
+ VariableCapture:: flowInsensitiveStep ( nodeFrom , nodeTo )
392
426
}
393
427
394
428
private predicate entrySsaDefinition ( SsaDefinitionExtNode n ) {
@@ -550,7 +584,7 @@ class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
550
584
}
551
585
552
586
/** An SSA definition for a `self` variable. */
553
- class SsaSelfDefinitionNode extends LocalSourceNode , SsaDefinitionExtNode {
587
+ class SsaSelfDefinitionNode extends SsaDefinitionExtNode {
554
588
private SelfVariable self ;
555
589
556
590
SsaSelfDefinitionNode ( ) { self = def .getSourceVariable ( ) }
@@ -559,6 +593,22 @@ class SsaSelfDefinitionNode extends LocalSourceNode, SsaDefinitionExtNode {
559
593
Scope getSelfScope ( ) { result = self .getDeclaringScope ( ) }
560
594
}
561
595
596
+ /** A data flow node representing a captured variable. Only used in type tracking. */
597
+ class CapturedVariableNode extends NodeImpl , TCapturedVariableNode {
598
+ private VariableCapture:: CapturedVariable variable ;
599
+
600
+ CapturedVariableNode ( ) { this = TCapturedVariableNode ( variable ) }
601
+
602
+ /** Gets the captured variable represented by this node. */
603
+ VariableCapture:: CapturedVariable getVariable ( ) { result = variable }
604
+
605
+ override CfgScope getCfgScope ( ) { result = variable .getCfgScope ( ) }
606
+
607
+ override Location getLocationImpl ( ) { result = variable .getLocation ( ) }
608
+
609
+ override string toStringImpl ( ) { result = "captured " + variable .getName ( ) }
610
+ }
611
+
562
612
/**
563
613
* A value returning statement, viewed as a node in a data flow graph.
564
614
*
@@ -1163,13 +1213,7 @@ private module OutNodes {
1163
1213
1164
1214
import OutNodes
1165
1215
1166
- predicate jumpStep ( Node pred , Node succ ) {
1167
- SsaImpl:: captureFlowIn ( _, pred .( SsaDefinitionExtNode ) .getDefinitionExt ( ) ,
1168
- succ .( SsaDefinitionExtNode ) .getDefinitionExt ( ) )
1169
- or
1170
- SsaImpl:: captureFlowOut ( _, pred .( SsaDefinitionExtNode ) .getDefinitionExt ( ) ,
1171
- succ .( SsaDefinitionExtNode ) .getDefinitionExt ( ) )
1172
- or
1216
+ predicate jumpStepTypeTracker ( Node pred , Node succ ) {
1173
1217
succ .asExpr ( ) .getExpr ( ) .( ConstantReadAccess ) .getValue ( ) = pred .asExpr ( ) .getExpr ( )
1174
1218
or
1175
1219
FlowSummaryImpl:: Private:: Steps:: summaryJumpStep ( pred .( FlowSummaryNode ) .getSummaryNode ( ) ,
@@ -1178,6 +1222,16 @@ predicate jumpStep(Node pred, Node succ) {
1178
1222
any ( AdditionalJumpStep s ) .step ( pred , succ )
1179
1223
}
1180
1224
1225
+ predicate jumpStep ( Node pred , Node succ ) {
1226
+ jumpStepTypeTracker ( pred , succ )
1227
+ or
1228
+ SsaImpl:: captureFlowIn ( _, pred .( SsaDefinitionExtNode ) .getDefinitionExt ( ) ,
1229
+ succ .( SsaDefinitionExtNode ) .getDefinitionExt ( ) )
1230
+ or
1231
+ SsaImpl:: captureFlowOut ( _, pred .( SsaDefinitionExtNode ) .getDefinitionExt ( ) ,
1232
+ succ .( SsaDefinitionExtNode ) .getDefinitionExt ( ) )
1233
+ }
1234
+
1181
1235
private ContentSet getKeywordContent ( string name ) {
1182
1236
exists ( ConstantValue:: ConstantSymbolValue key |
1183
1237
result .isSingleton ( TKnownElementContent ( key ) ) and
0 commit comments