@@ -137,22 +137,6 @@ module LocalFlow {
137137 nodeTo = getSelfParameterDefNode ( nodeFrom .( SelfParameterNodeImpl ) .getMethod ( ) )
138138 }
139139
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-
156140 /**
157141 * Holds if there is a local use-use flow step from `nodeFrom` to `nodeTo`
158142 * involving SSA definition `def`.
@@ -285,6 +269,53 @@ predicate isNonConstantExpr(CfgNodes::ExprCfgNode n) {
285269 not n .getExpr ( ) instanceof ConstantAccess
286270}
287271
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+
288319/** A collection of cached types and predicates to be evaluated in the same stage. */
289320cached
290321private module Cached {
@@ -296,6 +327,7 @@ private module Cached {
296327 TExprNode ( CfgNodes:: ExprCfgNode n ) { TaintTrackingPrivate:: forceCachingInSameStage ( ) } or
297328 TReturningNode ( CfgNodes:: ReturningCfgNode n ) or
298329 TSsaDefinitionExtNode ( SsaImpl:: DefinitionExt def ) or
330+ TCapturedVariableNode ( VariableCapture:: CapturedVariable v ) or
299331 TNormalParameterNode ( Parameter p ) {
300332 p instanceof SimpleParameter or
301333 p instanceof OptionalParameter or
@@ -389,6 +421,8 @@ private module Cached {
389421 LocalFlow:: localFlowSsaInputFromRead ( exprFrom , _, nodeTo ) and
390422 exprFrom = [ nodeFrom .asExpr ( ) , nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) ]
391423 )
424+ or
425+ VariableCapture:: flowInsensitiveStep ( nodeFrom , nodeTo )
392426 }
393427
394428 private predicate entrySsaDefinition ( SsaDefinitionExtNode n ) {
@@ -550,7 +584,7 @@ class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
550584}
551585
552586/** An SSA definition for a `self` variable. */
553- class SsaSelfDefinitionNode extends LocalSourceNode , SsaDefinitionExtNode {
587+ class SsaSelfDefinitionNode extends SsaDefinitionExtNode {
554588 private SelfVariable self ;
555589
556590 SsaSelfDefinitionNode ( ) { self = def .getSourceVariable ( ) }
@@ -559,6 +593,22 @@ class SsaSelfDefinitionNode extends LocalSourceNode, SsaDefinitionExtNode {
559593 Scope getSelfScope ( ) { result = self .getDeclaringScope ( ) }
560594}
561595
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+
562612/**
563613 * A value returning statement, viewed as a node in a data flow graph.
564614 *
@@ -1163,13 +1213,7 @@ private module OutNodes {
11631213
11641214import OutNodes
11651215
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 ) {
11731217 succ .asExpr ( ) .getExpr ( ) .( ConstantReadAccess ) .getValue ( ) = pred .asExpr ( ) .getExpr ( )
11741218 or
11751219 FlowSummaryImpl:: Private:: Steps:: summaryJumpStep ( pred .( FlowSummaryNode ) .getSummaryNode ( ) ,
@@ -1178,6 +1222,16 @@ predicate jumpStep(Node pred, Node succ) {
11781222 any ( AdditionalJumpStep s ) .step ( pred , succ )
11791223}
11801224
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+
11811235private ContentSet getKeywordContent ( string name ) {
11821236 exists ( ConstantValue:: ConstantSymbolValue key |
11831237 result .isSingleton ( TKnownElementContent ( key ) ) and
0 commit comments