@@ -17,6 +17,7 @@ private import semmle.python.Frameworks
1717import MatchUnpacking
1818import IterableUnpacking
1919import DataFlowDispatch
20+ import VariableCapture as VariableCapture
2021
2122/** Gets the callable in which this node occurs. */
2223DataFlowCallable nodeGetEnclosingCallable ( Node n ) { result = n .getEnclosingCallable ( ) }
@@ -384,197 +385,6 @@ module LocalFlow {
384385 }
385386}
386387
387- /** Provides logic related to captured variables. */
388- module VariableCapture {
389- private import codeql.dataflow.VariableCapture as Shared
390-
391- private module CaptureInput implements Shared:: InputSig< Location > {
392- private import python as PY
393-
394- additional class ExprCfgNode extends ControlFlowNode {
395- ExprCfgNode ( ) { isExpressionNode ( this ) }
396- }
397-
398- private predicate closureFlowStep ( ExprCfgNode nodeFrom , ExprCfgNode nodeTo ) {
399- // TODO: Other languages have an extra case here looking like
400- // simpleAstFlowStep(nodeFrom, nodeTo)
401- // we should investigate the potential benefit of adding that.
402- exists ( SsaVariable def |
403- def .getAUse ( ) = nodeTo and
404- def .getAnUltimateDefinition ( ) .getDefinition ( ) .( DefinitionNode ) .getValue ( ) = nodeFrom
405- )
406- }
407-
408- class Callable extends Scope {
409- predicate isConstructor ( ) { none ( ) }
410- }
411-
412- class BasicBlock extends PY:: BasicBlock {
413- Callable getEnclosingCallable ( ) { result = this .getScope ( ) }
414-
415- // TODO: check that this gives useful results
416- Location getLocation ( ) { result = super .getNode ( 0 ) .getLocation ( ) }
417- }
418-
419- BasicBlock getImmediateBasicBlockDominator ( BasicBlock bb ) {
420- result = bb .getImmediateDominator ( )
421- }
422-
423- BasicBlock getABasicBlockSuccessor ( BasicBlock bb ) { result = bb .getASuccessor ( ) }
424-
425- class CapturedVariable extends LocalVariable {
426- Function f ;
427-
428- CapturedVariable ( ) {
429- // note: captured variables originating on module scope is currently
430- // covered by global variable handling.
431- this .getScope ( ) = f and
432- this .getAnAccess ( ) .getScope ( ) != f
433- }
434-
435- Callable getCallable ( ) { result = f }
436-
437- Location getLocation ( ) { result = f .getLocation ( ) }
438-
439- /** Gets a scope that captures this variable. */
440- Scope getACapturingScope ( ) {
441- result = this .getAnAccess ( ) .getScope ( ) .getScope * ( ) and
442- result .getScope + ( ) = f
443- }
444- }
445-
446- class CapturedParameter extends CapturedVariable {
447- CapturedParameter ( ) { this .isParameter ( ) }
448-
449- ControlFlowNode getCfgNode ( ) { result .getNode ( ) .( Parameter ) = this .getAnAccess ( ) }
450- }
451-
452- class Expr extends ExprCfgNode {
453- predicate hasCfgNode ( BasicBlock bb , int i ) { this = bb .getNode ( i ) }
454- }
455-
456- class VariableWrite extends ControlFlowNode {
457- CapturedVariable v ;
458-
459- VariableWrite ( ) { this = v .getAStore ( ) .getAFlowNode ( ) }
460-
461- CapturedVariable getVariable ( ) { result = v }
462-
463- predicate hasCfgNode ( BasicBlock bb , int i ) { this = bb .getNode ( i ) }
464- }
465-
466- class VariableRead extends Expr {
467- CapturedVariable v ;
468-
469- VariableRead ( ) { this = v .getALoad ( ) .getAFlowNode ( ) }
470-
471- CapturedVariable getVariable ( ) { result = v }
472- }
473-
474- class ClosureExpr extends Expr {
475- ClosureExpr ( ) {
476- this .getNode ( ) instanceof CallableExpr
477- or
478- this .getNode ( ) instanceof Comp
479- }
480-
481- predicate hasBody ( Callable body ) {
482- body = this .getNode ( ) .( CallableExpr ) .getInnerScope ( )
483- or
484- body = this .getNode ( ) .( Comp ) .getFunction ( )
485- }
486-
487- predicate hasAliasedAccess ( Expr f ) { closureFlowStep + ( this , f ) and not closureFlowStep ( f , _) }
488- }
489- }
490-
491- class CapturedVariable = CaptureInput:: CapturedVariable ;
492-
493- class ClosureExpr = CaptureInput:: ClosureExpr ;
494-
495- module Flow = Shared:: Flow< Location , CaptureInput > ;
496-
497- private Flow:: ClosureNode asClosureNode ( Node n ) {
498- result = n .( SynthCaptureNode ) .getSynthesizedCaptureNode ( )
499- or
500- result .( Flow:: ExprNode ) .getExpr ( ) = n .( CfgNode ) .getNode ( )
501- or
502- result .( Flow:: VariableWriteSourceNode ) .getVariableWrite ( ) = n .( CfgNode ) .getNode ( )
503- or
504- result .( Flow:: ExprPostUpdateNode ) .getExpr ( ) =
505- n .( PostUpdateNode ) .getPreUpdateNode ( ) .( CfgNode ) .getNode ( )
506- or
507- result .( Flow:: ParameterNode ) .getParameter ( ) .getCfgNode ( ) = n .( CfgNode ) .getNode ( )
508- or
509- result .( Flow:: ThisParameterNode ) .getCallable ( ) =
510- n .( SynthCapturingClosureParameterNode ) .getCallable ( )
511- }
512-
513- predicate storeStep ( Node nodeFrom , CapturedVariableContent c , Node nodeTo ) {
514- Flow:: storeStep ( asClosureNode ( nodeFrom ) , c .getVariable ( ) , asClosureNode ( nodeTo ) )
515- }
516-
517- predicate readStep ( Node nodeFrom , CapturedVariableContent c , Node nodeTo ) {
518- Flow:: readStep ( asClosureNode ( nodeFrom ) , c .getVariable ( ) , asClosureNode ( nodeTo ) )
519- }
520-
521- predicate valueStep ( Node nodeFrom , Node nodeTo ) {
522- Flow:: localFlowStep ( asClosureNode ( nodeFrom ) , asClosureNode ( nodeTo ) )
523- }
524-
525- // Note: Learn from JS, https://github.com/github/codeql/pull/14412
526- // - JS: Capture flow
527- // - JS: Disallow consecutive captured contents
528- private module Debug {
529- predicate flowStoreStep (
530- Node nodeFrom , Flow:: ClosureNode closureNodeFrom , CapturedVariable v ,
531- Flow:: ClosureNode closureNodeTo , Node nodeTo
532- ) {
533- closureNodeFrom = asClosureNode ( nodeFrom ) and
534- closureNodeTo = asClosureNode ( nodeTo ) and
535- Flow:: storeStep ( closureNodeFrom , v , closureNodeTo )
536- }
537-
538- predicate unmappedFlowStoreStep (
539- Flow:: ClosureNode closureNodeFrom , CapturedVariable v , Flow:: ClosureNode closureNodeTo
540- ) {
541- Flow:: storeStep ( closureNodeFrom , v , closureNodeTo ) and
542- not flowStoreStep ( _, closureNodeFrom , v , closureNodeTo , _)
543- }
544-
545- predicate flowReadStep (
546- Node nodeFrom , Flow:: ClosureNode closureNodeFrom , CapturedVariable v ,
547- Flow:: ClosureNode closureNodeTo , Node nodeTo
548- ) {
549- closureNodeFrom = asClosureNode ( nodeFrom ) and
550- closureNodeTo = asClosureNode ( nodeTo ) and
551- Flow:: readStep ( closureNodeFrom , v , closureNodeTo )
552- }
553-
554- predicate unmappedFlowReadStep (
555- Flow:: ClosureNode closureNodeFrom , CapturedVariable v , Flow:: ClosureNode closureNodeTo
556- ) {
557- Flow:: readStep ( closureNodeFrom , v , closureNodeTo ) and
558- not flowReadStep ( _, closureNodeFrom , v , closureNodeTo , _)
559- }
560-
561- predicate flowValueStep (
562- Node nodeFrom , Flow:: ClosureNode closureNodeFrom , Flow:: ClosureNode closureNodeTo , Node nodeTo
563- ) {
564- closureNodeFrom = asClosureNode ( nodeFrom ) and
565- closureNodeTo = asClosureNode ( nodeTo ) and
566- Flow:: localFlowStep ( closureNodeFrom , closureNodeTo )
567- }
568-
569- predicate unmappedFlowValueStep (
570- Flow:: ClosureNode closureNodeFrom , Flow:: ClosureNode closureNodeTo
571- ) {
572- Flow:: localFlowStep ( closureNodeFrom , closureNodeTo ) and
573- not flowValueStep ( _, closureNodeFrom , closureNodeTo , _)
574- }
575- }
576- }
577-
578388//--------
579389// Local flow
580390//--------
0 commit comments