11private import javascript as js
22private import semmle.javascript.dataflow.internal.DataFlowNode
3+ private import semmle.javascript.dataflow.internal.VariableOrThis
34private import codeql.dataflow.VariableCapture
45private import semmle.javascript.dataflow.internal.sharedlib.DataFlowImplCommon as DataFlowImplCommon
56
@@ -51,7 +52,7 @@ module VariableCaptureConfig implements InputSig<js::DbLocation> {
5152 )
5253 }
5354
54- class CapturedVariable extends js :: LocalVariable {
55+ class CapturedVariable extends LocalVariableOrThis {
5556 CapturedVariable ( ) {
5657 DataFlowImplCommon:: forceCachingInSameStage ( ) and
5758 this .isCaptured ( ) and
@@ -63,7 +64,9 @@ module VariableCaptureConfig implements InputSig<js::DbLocation> {
6364
6465 additional predicate captures ( js:: Function fun , CapturedVariable variable ) {
6566 (
66- variable .getAnAccess ( ) .getContainer ( ) .getFunctionBoundary ( ) = fun
67+ variable .asLocalVariable ( ) .getAnAccess ( ) .getContainer ( ) .getFunctionBoundary ( ) = fun
68+ or
69+ variable .getAThisUse ( ) .getUseContainer ( ) = fun
6770 or
6871 exists ( js:: Function inner |
6972 captures ( inner , variable ) and
@@ -122,7 +125,8 @@ module VariableCaptureConfig implements InputSig<js::DbLocation> {
122125 private predicate isCapturedByOwnInitializer ( js:: VariableDeclarator decl ) {
123126 exists ( js:: Function function |
124127 function = getACapturingFunctionInTree ( decl .getInit ( ) ) and
125- captures ( function , decl .getBindingPattern ( ) .( js:: VarDecl ) .getVariable ( ) )
128+ captures ( function ,
129+ LocalVariableOrThis:: variable ( decl .getBindingPattern ( ) .( js:: VarDecl ) .getVariable ( ) ) )
126130 )
127131 }
128132
@@ -141,7 +145,7 @@ module VariableCaptureConfig implements InputSig<js::DbLocation> {
141145 }
142146
143147 class CapturedParameter extends CapturedVariable {
144- CapturedParameter ( ) { this .isParameter ( ) }
148+ CapturedParameter ( ) { this .asLocalVariable ( ) . isParameter ( ) or exists ( this . asThisContainer ( ) ) }
145149 }
146150
147151 class Expr extends js:: AST:: ValueNode {
@@ -152,10 +156,10 @@ module VariableCaptureConfig implements InputSig<js::DbLocation> {
152156 }
153157 }
154158
155- class VariableRead extends Expr instanceof js:: VarAccess , js :: RValue {
159+ class VariableRead extends Expr instanceof js:: ControlFlowNode {
156160 private CapturedVariable variable ;
157161
158- VariableRead ( ) { this = variable .getAnAccess ( ) }
162+ VariableRead ( ) { this = variable .getAUse ( ) }
159163
160164 CapturedVariable getVariable ( ) { result = variable }
161165 }
@@ -178,7 +182,7 @@ module VariableCaptureConfig implements InputSig<js::DbLocation> {
178182 private newtype TVariableWrite =
179183 MkExplicitVariableWrite ( js:: VarRef pattern ) {
180184 exists ( js:: DataFlow:: lvalueNodeInternal ( pattern ) ) and
181- pattern . getVariable ( ) instanceof CapturedVariable
185+ any ( CapturedVariable v ) . asLocalVariable ( ) = pattern . getVariable ( )
182186 } or
183187 MkImplicitVariableInit ( CapturedVariable v ) { not v instanceof CapturedParameter }
184188
@@ -200,7 +204,7 @@ module VariableCaptureConfig implements InputSig<js::DbLocation> {
200204
201205 ExplicitVariableWrite ( ) { this = MkExplicitVariableWrite ( pattern ) }
202206
203- override CapturedVariable getVariable ( ) { result = pattern .getVariable ( ) }
207+ override CapturedVariable getVariable ( ) { result . asLocalVariable ( ) = pattern .getVariable ( ) }
204208
205209 override string toString ( ) { result = pattern .toString ( ) }
206210
@@ -248,7 +252,9 @@ module VariableCaptureConfig implements InputSig<js::DbLocation> {
248252 override predicate hasCfgNode ( BasicBlock bb , int i ) {
249253 // 'i' would normally be bound to 0, but we lower it to -1 so FunctionDeclStmts can be evaluated
250254 // at index 0.
251- any ( js:: SsaImplicitInit def ) .definesAt ( bb , _, variable ) and i = - 1
255+ any ( js:: SsaImplicitInit def ) .definesAt ( bb , _, variable .asLocalVariable ( ) ) and i = - 1
256+ or
257+ bb .( js:: EntryBasicBlock ) .getContainer ( ) = variable .asThisContainer ( ) and i = - 1
252258 }
253259 }
254260
@@ -266,7 +272,13 @@ module VariableCaptureOutput = Flow<js::DbLocation, VariableCaptureConfig>;
266272js:: DataFlow:: Node getNodeFromClosureNode ( VariableCaptureOutput:: ClosureNode node ) {
267273 result = TValueNode ( node .( VariableCaptureOutput:: ExprNode ) .getExpr ( ) )
268274 or
269- result = TValueNode ( node .( VariableCaptureOutput:: ParameterNode ) .getParameter ( ) .getADeclaration ( ) ) // TODO: is this subsumed by the ExprNode case?
275+ result =
276+ TValueNode ( node .( VariableCaptureOutput:: ParameterNode )
277+ .getParameter ( )
278+ .asLocalVariable ( )
279+ .getADeclaration ( ) ) // TODO: is this subsumed by the ExprNode case?
280+ or
281+ result = TThisNode ( node .( VariableCaptureOutput:: ParameterNode ) .getParameter ( ) .asThisContainer ( ) )
270282 or
271283 result = TExprPostUpdateNode ( node .( VariableCaptureOutput:: ExprPostUpdateNode ) .getExpr ( ) )
272284 or
0 commit comments