@@ -2,6 +2,7 @@ overlay[local]
22module ;
33
44private import TreeSitter
5+ private import codeql.namebinding.LocalNameBinding
56private import codeql.ruby.AST
67private import codeql.ruby.CFG
78private import codeql.ruby.ast.internal.AST
@@ -137,11 +138,97 @@ private predicate scopeAssigns(Scope::Range scope, string name, Ruby::AstNode i)
137138 name = variableNameInScope ( i , scope )
138139}
139140
141+ private module Input implements LocalNameBindingInputSig< Location > {
142+ predicate cacheRevRef ( ) { exists ( TVariable v ) implies any ( ) }
143+
144+ class AstNode = Ruby:: AstNode ;
145+
146+ AstNode getChild ( AstNode parent , int index ) {
147+ parent = parentOf ( result ) and
148+ (
149+ index = result .getParentIndex ( )
150+ or
151+ not exists ( result .getParentIndex ( ) ) and
152+ index = - 1
153+ )
154+ }
155+
156+ class Conditional extends AstNode {
157+ Conditional ( ) { none ( ) }
158+
159+ AstNode getCondition ( ) { none ( ) }
160+
161+ AstNode getThen ( ) { none ( ) }
162+
163+ AstNode getElse ( ) { none ( ) }
164+ }
165+
166+ class ShadowingDecl extends AstNode {
167+ ShadowingDecl ( ) { none ( ) }
168+
169+ AstNode getLhs ( ) { none ( ) }
170+
171+ AstNode getRhs ( ) { none ( ) }
172+
173+ AstNode getElse ( ) { none ( ) }
174+ }
175+
176+ predicate declInScope ( AstNode definingNode , string name , AstNode scope ) {
177+ scopeDefinesParameterVariable ( scope , name , definingNode , _)
178+ or
179+ definingNode =
180+ min ( Ruby:: AstNode other |
181+ scopeAssigns ( scope , name , other )
182+ |
183+ other order by other .getLocation ( ) .getStartLine ( ) , other .getLocation ( ) .getStartColumn ( )
184+ ) and
185+ not scopeDefinesParameterVariable ( scope , name , _, _) and
186+ not inherits ( scope , name , _)
187+ }
188+
189+ predicate implicitDeclInScope ( string name , AstNode scope ) {
190+ name = "self" and
191+ scope instanceof SelfBase:: Range
192+ }
193+
194+ predicate isTopScope ( AstNode scope ) {
195+ scope instanceof Scope:: Range and
196+ not (
197+ scope instanceof Ruby:: Block or
198+ scope instanceof Ruby:: DoBlock or
199+ scope instanceof Ruby:: Lambda
200+ )
201+ }
202+
203+ predicate accessCand ( AstNode n , string name ) {
204+ name = variableNameInScope ( n , _) and
205+ (
206+ explicitAssignmentNode ( n , _)
207+ or
208+ implicitAssignmentNode ( n )
209+ or
210+ scopeDefinesParameterVariable ( _, _, n , _)
211+ or
212+ vcall ( n )
213+ // or
214+ // n = any(Ruby::VariableReferencePattern vr).getName()
215+ )
216+ or
217+ n instanceof Ruby:: Self and
218+ name = "self"
219+ }
220+ }
221+
222+ private import LocalNameBinding< Location , Input >
223+
140224cached
141225private module Cached {
142226 cached
143227 newtype TVariable =
144- TGlobalVariable ( string name ) { name = any ( Ruby:: GlobalVariable var ) .getValue ( ) } or
228+ TGlobalVariable ( string name ) {
229+ CachedStage:: ref ( ) and
230+ name = any ( Ruby:: GlobalVariable var ) .getValue ( )
231+ } or
145232 TClassVariable ( Scope:: Range scope , string name , Ruby:: AstNode decl ) {
146233 decl =
147234 min ( Ruby:: ClassVariable other |
@@ -158,19 +245,7 @@ private module Cached {
158245 other order by other .getLocation ( ) .getStartLine ( ) , other .getLocation ( ) .getStartColumn ( )
159246 )
160247 } or
161- TLocalVariableReal ( Scope:: Range scope , string name , Ruby:: AstNode i ) {
162- scopeDefinesParameterVariable ( scope , name , i , _)
163- or
164- i =
165- min ( Ruby:: AstNode other |
166- scopeAssigns ( scope , name , other )
167- |
168- other order by other .getLocation ( ) .getStartLine ( ) , other .getLocation ( ) .getStartColumn ( )
169- ) and
170- not scopeDefinesParameterVariable ( scope , name , _, _) and
171- not inherits ( scope , name , _)
172- } or
173- TSelfVariable ( SelfBase:: Range scope ) or
248+ TLocalVariableReal ( Local l ) or
174249 TLocalVariableSynth ( AstNode n , int i ) { any ( Synthesis s ) .localVariable ( n , i ) }
175250
176251 // Db types that can be vcalls
@@ -321,39 +396,20 @@ private module Cached {
321396 i = any ( Ruby:: ExpressionReferencePattern x ) .getValue ( )
322397 }
323398
324- pragma [ nomagic]
325- private predicate hasScopeAndName ( VariableReal variable , Scope:: Range scope , string name ) {
326- variable .getNameImpl ( ) = name and
327- scope = variable .getDeclaringScopeImpl ( )
328- }
329-
330399 cached
331400 predicate access ( Ruby:: AstNode access , VariableReal variable ) {
332- exists ( string name , Scope:: Range scope |
333- pragma [ only_bind_into ] ( name ) = variableNameInScope ( access , scope )
334- |
335- hasScopeAndName ( variable , scope , name ) and
336- not access .getLocation ( ) .strictlyBefore ( variable .getLocationImpl ( ) ) and
337- // In case of overlapping parameter names, later parameters should not
338- // be considered accesses to the first parameter
339- if parameterAssignment ( _, _, access , _)
340- then scopeDefinesParameterVariable ( _, _, access , _)
341- else any ( )
342- or
343- exists ( Scope:: Range declScope |
344- hasScopeAndName ( variable , declScope , pragma [ only_bind_into ] ( name ) ) and
345- inherits ( scope , name , declScope )
346- )
401+ exists ( Local l | variable = TLocalVariableReal ( l ) |
402+ access = l .getAnAccess ( ) and
403+ not access .getLocation ( ) .strictlyBefore ( l .getDefiningNode ( ) .getLocation ( ) )
347404 )
348405 }
349406
350407 private class Access extends Ruby:: Token {
351408 Access ( ) {
352- access ( this . ( Ruby :: Identifier ) , _) or
409+ access ( this , _) or
353410 this instanceof Ruby:: GlobalVariable or
354411 this instanceof Ruby:: InstanceVariable or
355- this instanceof Ruby:: ClassVariable or
356- this instanceof Ruby:: Self
412+ this instanceof Ruby:: ClassVariable
357413 }
358414 }
359415
@@ -429,10 +485,9 @@ abstract class VariableImpl extends TVariable {
429485 abstract Location getLocationImpl ( ) ;
430486}
431487
432- class TVariableReal =
433- TGlobalVariable or TClassVariable or TInstanceVariable or TLocalVariableReal or TSelfVariable ;
488+ class TVariableReal = TGlobalVariable or TClassVariable or TInstanceVariable or TLocalVariableReal ;
434489
435- class TLocalVariable = TLocalVariableReal or TLocalVariableSynth or TSelfVariable ;
490+ class TLocalVariable = TLocalVariableReal or TLocalVariableSynth ;
436491
437492/**
438493 * A "real" (i.e. non-synthesized) variable. This class only exists to
@@ -458,19 +513,19 @@ private class VariableRealAdapter extends VariableImpl, TVariableReal instanceof
458513}
459514
460515class LocalVariableReal extends VariableReal , TLocalVariableReal {
461- private Scope:: Range scope ;
462- private string name ;
463- private Ruby:: AstNode i ;
516+ private Local l ;
464517
465- LocalVariableReal ( ) { this = TLocalVariableReal ( scope , name , i ) }
518+ LocalVariableReal ( ) { this = TLocalVariableReal ( l ) }
466519
467- final override string getNameImpl ( ) { result = name }
520+ Ruby :: AstNode getDefiningNode ( ) { result = l . getDefiningNode ( ) }
468521
469- final override Location getLocationImpl ( ) { result = i . getLocation ( ) }
522+ final override string getNameImpl ( ) { result = l . getName ( ) }
470523
471- final override Scope:: Range getDeclaringScopeImpl ( ) { result = scope }
524+ final override Location getLocationImpl ( ) { result = l .getLocation ( ) }
525+
526+ final override Scope:: Range getDeclaringScopeImpl ( ) { result = l .getScope ( ) }
472527
473- final VariableAccess getDefiningAccessImpl ( ) { toGenerated ( result ) = i }
528+ final VariableAccess getDefiningAccessImpl ( ) { toGenerated ( result ) = l . getDefiningNode ( ) }
474529}
475530
476531class LocalVariableSynth extends VariableImpl , TLocalVariableSynth {
@@ -531,32 +586,18 @@ class ClassVariableImpl extends VariableReal, TClassVariable {
531586 final override Scope:: Range getDeclaringScopeImpl ( ) { result = scope }
532587}
533588
534- class SelfVariableImpl extends VariableReal , TSelfVariable {
535- private SelfBase:: Range scope ;
536-
537- SelfVariableImpl ( ) { this = TSelfVariable ( scope ) }
589+ class SelfVariableImpl extends LocalVariableReal {
590+ private ImplicitLocal l ;
538591
539- final override string getNameImpl ( ) { result = "self" }
540-
541- final override Location getLocationImpl ( ) { result = scope .getLocation ( ) }
542-
543- final override Scope:: Range getDeclaringScopeImpl ( ) { result = scope }
592+ SelfVariableImpl ( ) { this = TLocalVariableReal ( l ) }
544593}
545594
546595abstract class VariableAccessImpl extends Expr , TVariableAccess {
547596 abstract VariableImpl getVariableImpl ( ) ;
548597}
549598
550599module LocalVariableAccess {
551- predicate range ( Ruby:: Identifier id , TLocalVariableReal v ) {
552- access ( id , v ) and
553- (
554- explicitWriteAccess ( id , _) or
555- implicitWriteAccess ( id ) or
556- vcall ( id ) or
557- id = any ( Ruby:: VariableReferencePattern vr ) .getName ( )
558- )
559- }
600+ predicate range ( Ruby:: AstNode n , TLocalVariableReal v ) { access ( n , v ) }
560601}
561602
562603class TVariableAccessReal =
@@ -681,7 +722,8 @@ private class SelfVariableAccessReal extends SelfVariableAccessImpl, TSelfReal {
681722
682723 SelfVariableAccessReal ( ) {
683724 exists ( Ruby:: Self self |
684- this = TSelfReal ( self ) and var = TSelfVariable ( scopeOf ( self ) .getEnclosingSelfScope ( ) )
725+ this = TSelfReal ( self ) and
726+ LocalVariableAccess:: range ( self , var )
685727 )
686728 }
687729
0 commit comments