77import go
88private import codeql.ssa.Ssa as SsaImplCommon
99
10+ class NonFileScopeLocalVariable extends LocalVariable {
11+ NonFileScopeLocalVariable ( ) { not this .getScope ( ) instanceof FileScope }
12+ }
13+
14+ cached
15+ newtype TSsaSourceVariable =
16+ MkNonCapturedVariableVariable ( NonFileScopeLocalVariable v ) or
17+ MkCapturedVariableVariable ( FuncDef root , NonFileScopeLocalVariable v ) { v .isCaptured ( root ) }
18+
1019cached
1120private module Internal {
1221 /** Holds if the `i`th node of `bb` defines `v`. */
1322 cached
1423 predicate defAt ( ReachableBasicBlock bb , int i , SsaSourceVariable v ) {
15- bb .getNode ( i ) .( IR:: Instruction ) .writes ( v , _)
24+ exists ( IR:: Instruction inst | inst = bb .getNode ( i ) .( IR:: Instruction ) |
25+ inst .writes ( v .getVariable ( ) , _) and
26+ inst .getRoot ( ) = v .getRoot ( )
27+ )
1628 }
1729
1830 /** Holds if the `i`th node of `bb` reads `v`. */
1931 cached
2032 predicate useAt ( ReachableBasicBlock bb , int i , SsaSourceVariable v ) {
21- bb .getNode ( i ) .( IR:: Instruction ) .reads ( v )
33+ exists ( IR:: Instruction inst | inst = bb .getNode ( i ) .( IR:: Instruction ) |
34+ inst .reads ( v .getVariable ( ) ) and
35+ inst .getRoot ( ) = v .getRoot ( )
36+ )
2237 }
2338
2439 /**
2540 * Holds if `v` is a captured variable which is declared in `declFun` and read in `useFun`.
2641 */
27- private predicate readsCapturedVar ( FuncDef useFun , SsaSourceVariable v , FuncDef declFun ) {
42+ private predicate readsCapturedVar ( FuncDef useFun , NonFileScopeLocalVariable v , FuncDef declFun ) {
2843 declFun = v .getDeclaringFunction ( ) and
2944 useFun = any ( IR:: Instruction u | u .reads ( v ) ) .getRoot ( ) and
30- v .isCaptured ( )
45+ v .isCaptured ( _ )
3146 }
3247
3348 /** Holds if the `i`th node of `bb` in function `f` is an entry node. */
@@ -50,8 +65,15 @@ private module Internal {
5065 * introduced depends on whether `v` is live at this point in the program.
5166 */
5267 cached
53- predicate mayCapture ( ReachableBasicBlock bb , int i , SsaSourceVariable v ) {
54- exists ( FuncDef capturingContainer , FuncDef declContainer |
68+ predicate mayCapture (
69+ ReachableBasicBlock bb , int i , SsaSourceVariable capturedVar , SsaSourceVariable closureVar
70+ ) {
71+ exists ( LocalVariable v , FuncDef capturingContainer , FuncDef declContainer |
72+ v = capturedVar .getVariable ( ) and
73+ v = closureVar .getVariable ( ) and
74+ declContainer = capturedVar .getRoot ( ) and
75+ capturingContainer = closureVar .getRoot ( )
76+ |
5577 // capture initial value of variable declared in enclosing scope
5678 readsCapturedVar ( capturingContainer , v , declContainer ) and
5779 capturingContainer != declContainer and
@@ -76,7 +98,7 @@ private module Internal {
7698 private predicate ref ( ReachableBasicBlock bb , int i , SsaSourceVariable v , RefKind tp ) {
7799 useAt ( bb , i , v ) and tp = ReadRef ( )
78100 or
79- ( mayCapture ( bb , i , v ) or defAt ( bb , i , v ) ) and
101+ ( mayCapture ( bb , i , v , _ ) or defAt ( bb , i , v ) ) and
80102 tp = WriteRef ( )
81103 }
82104
@@ -114,7 +136,7 @@ private module Internal {
114136 /**
115137 * Holds if `v` is assigned outside its declaring function.
116138 */
117- private predicate assignedThroughClosure ( SsaSourceVariable v ) {
139+ private predicate assignedThroughClosure ( NonFileScopeLocalVariable v ) {
118140 any ( IR:: Instruction def | def .writes ( v , _) ) .getRoot ( ) != v .getDeclaringFunction ( )
119141 }
120142
@@ -407,6 +429,8 @@ private module Internal {
407429 predicate variableWrite ( BasicBlock bb , int i , SourceVariable v , boolean certain ) {
408430 defAt ( bb , i , v ) and
409431 certain = true
432+ or
433+ mayCapture ( bb , i , _, v ) and certain = true
410434 }
411435
412436 /**
@@ -417,7 +441,7 @@ private module Internal {
417441 predicate variableRead ( BasicBlock bb , int i , SourceVariable v , boolean certain ) {
418442 useAt ( bb , i , v ) and certain = true
419443 or
420- mayCapture ( bb , i , v ) and certain = false
444+ mayCapture ( bb , i , v , _ ) and certain = true
421445 }
422446 }
423447
@@ -434,4 +458,4 @@ private module Internal {
434458
435459import Internal
436460
437- predicate captures = Internal:: mayCapture / 3 ;
461+ predicate captures = Internal:: mayCapture / 4 ;
0 commit comments