@@ -9,6 +9,23 @@ private import FlowSummaryImplSpecific as FlowSummaryImplSpecific
99private import codeql.ruby.dataflow.FlowSummary
1010private import codeql.ruby.dataflow.SSA
1111
12+ /**
13+ * A `LocalSourceNode` for a `self` variable. This is either an implicit `self`
14+ * parameter or an implicit SSA entry definition.
15+ */
16+ private class SelfLocalSourceNode extends DataFlow:: LocalSourceNode {
17+ private SelfVariable self ;
18+
19+ SelfLocalSourceNode ( ) {
20+ self = this .( SelfParameterNode ) .getSelfVariable ( )
21+ or
22+ self = this .( SsaSelfDefinitionNode ) .getVariable ( )
23+ }
24+
25+ /** Gets the `self` variable. */
26+ SelfVariable getVariable ( ) { result = self }
27+ }
28+
1229newtype TReturnKind =
1330 TNormalReturnKind ( ) or
1431 TBreakReturnKind ( ) or
@@ -316,7 +333,7 @@ private predicate extendCall(DataFlow::ExprNode receiver, Module m) {
316333 exists ( DataFlow:: CallNode extendCall |
317334 extendCall .getMethodName ( ) = "extend" and
318335 exists ( DataFlow:: LocalSourceNode sourceNode | sourceNode .flowsTo ( extendCall .getArgument ( _) ) |
319- selfInModule ( sourceNode .( SsaSelfDefinitionNode ) .getVariable ( ) , m ) or
336+ selfInModule ( sourceNode .( SelfLocalSourceNode ) .getVariable ( ) , m ) or
320337 m = resolveConstantReadAccess ( sourceNode .asExpr ( ) .getExpr ( ) )
321338 ) and
322339 receiver = extendCall .getReceiver ( )
@@ -329,7 +346,7 @@ private predicate extendCallModule(Module m, Module n) {
329346 exists ( DataFlow:: LocalSourceNode receiver , DataFlow:: ExprNode e |
330347 receiver .flowsTo ( e ) and extendCall ( e , n )
331348 |
332- selfInModule ( receiver .( SsaSelfDefinitionNode ) .getVariable ( ) , m ) or
349+ selfInModule ( receiver .( SelfLocalSourceNode ) .getVariable ( ) , m ) or
333350 m = resolveConstantReadAccess ( receiver .asExpr ( ) .getExpr ( ) )
334351 )
335352}
@@ -502,12 +519,12 @@ private predicate isStandardNewCall(RelevantCall new, Module m, boolean exact) {
502519 exact = true
503520 or
504521 // `self.new` inside a module
505- selfInModule ( sourceNode .( SsaSelfDefinitionNode ) .getVariable ( ) , m ) and
522+ selfInModule ( sourceNode .( SelfLocalSourceNode ) .getVariable ( ) , m ) and
506523 exact = true
507524 or
508525 // `self.new` inside a singleton method
509526 exists ( MethodBase caller |
510- selfInMethod ( sourceNode .( SsaSelfDefinitionNode ) .getVariable ( ) , caller , m ) and
527+ selfInMethod ( sourceNode .( SelfLocalSourceNode ) .getVariable ( ) , caller , m ) and
511528 singletonMethod ( caller , _, _) and
512529 exact = false
513530 )
@@ -573,7 +590,7 @@ private predicate isInstance(DataFlow::Node n, Module tp, boolean exact) {
573590 // `self` reference in method or top-level (but not in module or singleton method,
574591 // where instance methods cannot be called; only singleton methods)
575592 n =
576- any ( SsaSelfDefinitionNode self |
593+ any ( SelfLocalSourceNode self |
577594 exists ( MethodBase m |
578595 selfInMethod ( self .getVariable ( ) , m , tp ) and
579596 not m instanceof SingletonMethod and
@@ -607,10 +624,10 @@ private DataFlow::Node trackInstance(Module tp, boolean exact, TypeTracker t) {
607624 m = resolveConstantReadAccess ( result .asExpr ( ) .getExpr ( ) )
608625 or
609626 // needed for e.g. `self.include`
610- selfInModule ( result .( SsaSelfDefinitionNode ) .getVariable ( ) , m )
627+ selfInModule ( result .( SelfLocalSourceNode ) .getVariable ( ) , m )
611628 or
612629 // needed for e.g. `self.puts`
613- selfInMethod ( result .( SsaSelfDefinitionNode ) .getVariable ( ) , any ( SingletonMethod sm ) , m )
630+ selfInMethod ( result .( SelfLocalSourceNode ) .getVariable ( ) , any ( SingletonMethod sm ) , m )
614631 )
615632 )
616633 or
@@ -970,7 +987,7 @@ private DataFlow::Node trackSingletonMethodOnInstance(MethodBase method, string
970987/** Holds if a `self` access may be the receiver of `call` directly inside module `m`. */
971988pragma [ nomagic]
972989private predicate selfInModuleFlowsToMethodCallReceiver ( RelevantCall call , Module m , string method ) {
973- exists ( SsaSelfDefinitionNode self |
990+ exists ( SelfLocalSourceNode self |
974991 flowsToMethodCallReceiver ( call , self , method ) and
975992 selfInModule ( self .getVariable ( ) , m )
976993 )
@@ -984,7 +1001,7 @@ pragma[nomagic]
9841001private predicate selfInSingletonMethodFlowsToMethodCallReceiver (
9851002 RelevantCall call , Module m , string method
9861003) {
987- exists ( SsaSelfDefinitionNode self , MethodBase caller |
1004+ exists ( SelfLocalSourceNode self , MethodBase caller |
9881005 flowsToMethodCallReceiver ( call , self , method ) and
9891006 selfInMethod ( self .getVariable ( ) , caller , m ) and
9901007 singletonMethod ( caller , _, _)
@@ -1062,10 +1079,13 @@ private CfgScope getTargetSingleton(RelevantCall call, string method) {
10621079 */
10631080pragma [ nomagic]
10641081private predicate argMustFlowToReceiver (
1065- RelevantCall ctx , DataFlow:: LocalSourceNode source , DataFlow:: Node arg ,
1066- SsaDefinitionExtNode paramDef , RelevantCall call , Callable encl , string name
1082+ RelevantCall ctx , DataFlow:: LocalSourceNode source , DataFlow:: Node arg , RelevantCall call ,
1083+ Callable encl , string name
10671084) {
1068- exists ( ParameterNodeImpl p , ParameterPosition ppos , ArgumentPosition apos |
1085+ exists (
1086+ ParameterNodeImpl p , SsaDefinitionExtNode paramDef , ParameterPosition ppos ,
1087+ ArgumentPosition apos
1088+ |
10691089 // the receiver of `call` references `p`
10701090 exists ( DataFlow:: Node receiver |
10711091 LocalFlow:: localFlowSsaParamInput ( p , paramDef ) and
@@ -1106,7 +1126,7 @@ private predicate mayBenefitFromCallContextInitialize(
11061126 RelevantCall ctx , RelevantCall new , DataFlow:: Node arg , Callable encl , Module tp , string name
11071127) {
11081128 exists ( DataFlow:: LocalSourceNode source |
1109- argMustFlowToReceiver ( ctx , pragma [ only_bind_into ] ( source ) , arg , _ , new , encl , "new" ) and
1129+ argMustFlowToReceiver ( ctx , pragma [ only_bind_into ] ( source ) , arg , new , encl , "new" ) and
11101130 source = trackModuleAccess ( tp ) and
11111131 name = "initialize" and
11121132 exists ( lookupMethod ( tp , name ) )
@@ -1127,7 +1147,7 @@ private predicate mayBenefitFromCallContextInstance(
11271147 string name
11281148) {
11291149 exists ( DataFlow:: LocalSourceNode source |
1130- argMustFlowToReceiver ( ctx , pragma [ only_bind_into ] ( source ) , arg , _ , call , encl ,
1150+ argMustFlowToReceiver ( ctx , pragma [ only_bind_into ] ( source ) , arg , call , encl ,
11311151 pragma [ only_bind_into ] ( name ) ) and
11321152 source = trackInstance ( tp , exact ) and
11331153 exists ( lookupMethod ( tp , pragma [ only_bind_into ] ( name ) ) )
@@ -1148,7 +1168,7 @@ private predicate mayBenefitFromCallContextSingleton(
11481168 string name
11491169) {
11501170 exists ( DataFlow:: LocalSourceNode source |
1151- argMustFlowToReceiver ( ctx , pragma [ only_bind_into ] ( source ) , pragma [ only_bind_into ] ( arg ) , _ , call ,
1171+ argMustFlowToReceiver ( ctx , pragma [ only_bind_into ] ( source ) , pragma [ only_bind_into ] ( arg ) , call ,
11521172 encl , pragma [ only_bind_into ] ( name ) ) and
11531173 exists ( lookupSingletonMethod ( tp , pragma [ only_bind_into ] ( name ) , exact ) )
11541174 |
@@ -1216,21 +1236,18 @@ DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
12161236 or
12171237 // `ctx` cannot provide a type bound, and the receiver of the call is `self`;
12181238 // in this case, still apply an open-world assumption
1219- exists (
1220- RelevantCall call0 , RelevantCall ctx0 , DataFlow:: Node arg , SsaSelfDefinitionNode self ,
1221- string name
1222- |
1239+ exists ( RelevantCall call0 , RelevantCall ctx0 , DataFlow:: Node arg , string name |
12231240 call0 = call .asCall ( ) and
12241241 ctx0 = ctx .asCall ( ) and
1225- argMustFlowToReceiver ( ctx0 , _, arg , self , call0 , _, name ) and
1242+ argMustFlowToReceiver ( ctx0 , _, arg , call0 , _, name ) and
12261243 not mayBenefitFromCallContextInitialize ( ctx0 , call0 , arg , _, _, _) and
12271244 not mayBenefitFromCallContextInstance ( ctx0 , call0 , arg , _, _, _, name ) and
12281245 not mayBenefitFromCallContextSingleton ( ctx0 , call0 , arg , _, _, _, name ) and
12291246 result .asCallable ( ) = viableSourceCallable ( call0 )
12301247 )
12311248 or
12321249 // library calls should always be able to resolve
1233- argMustFlowToReceiver ( ctx .asCall ( ) , _, _, _ , call .asCall ( ) , _, _) and
1250+ argMustFlowToReceiver ( ctx .asCall ( ) , _, _, call .asCall ( ) , _, _) and
12341251 result = viableLibraryCallable ( call )
12351252 )
12361253}
0 commit comments