@@ -9,6 +9,23 @@ private import FlowSummaryImplSpecific as FlowSummaryImplSpecific
9
9
private import codeql.ruby.dataflow.FlowSummary
10
10
private import codeql.ruby.dataflow.SSA
11
11
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
+
12
29
newtype TReturnKind =
13
30
TNormalReturnKind ( ) or
14
31
TBreakReturnKind ( ) or
@@ -316,7 +333,7 @@ private predicate extendCall(DataFlow::ExprNode receiver, Module m) {
316
333
exists ( DataFlow:: CallNode extendCall |
317
334
extendCall .getMethodName ( ) = "extend" and
318
335
exists ( DataFlow:: LocalSourceNode sourceNode | sourceNode .flowsTo ( extendCall .getArgument ( _) ) |
319
- selfInModule ( sourceNode .( SsaSelfDefinitionNode ) .getVariable ( ) , m ) or
336
+ selfInModule ( sourceNode .( SelfLocalSourceNode ) .getVariable ( ) , m ) or
320
337
m = resolveConstantReadAccess ( sourceNode .asExpr ( ) .getExpr ( ) )
321
338
) and
322
339
receiver = extendCall .getReceiver ( )
@@ -329,7 +346,7 @@ private predicate extendCallModule(Module m, Module n) {
329
346
exists ( DataFlow:: LocalSourceNode receiver , DataFlow:: ExprNode e |
330
347
receiver .flowsTo ( e ) and extendCall ( e , n )
331
348
|
332
- selfInModule ( receiver .( SsaSelfDefinitionNode ) .getVariable ( ) , m ) or
349
+ selfInModule ( receiver .( SelfLocalSourceNode ) .getVariable ( ) , m ) or
333
350
m = resolveConstantReadAccess ( receiver .asExpr ( ) .getExpr ( ) )
334
351
)
335
352
}
@@ -502,12 +519,12 @@ private predicate isStandardNewCall(RelevantCall new, Module m, boolean exact) {
502
519
exact = true
503
520
or
504
521
// `self.new` inside a module
505
- selfInModule ( sourceNode .( SsaSelfDefinitionNode ) .getVariable ( ) , m ) and
522
+ selfInModule ( sourceNode .( SelfLocalSourceNode ) .getVariable ( ) , m ) and
506
523
exact = true
507
524
or
508
525
// `self.new` inside a singleton method
509
526
exists ( MethodBase caller |
510
- selfInMethod ( sourceNode .( SsaSelfDefinitionNode ) .getVariable ( ) , caller , m ) and
527
+ selfInMethod ( sourceNode .( SelfLocalSourceNode ) .getVariable ( ) , caller , m ) and
511
528
singletonMethod ( caller , _, _) and
512
529
exact = false
513
530
)
@@ -573,7 +590,7 @@ private predicate isInstance(DataFlow::Node n, Module tp, boolean exact) {
573
590
// `self` reference in method or top-level (but not in module or singleton method,
574
591
// where instance methods cannot be called; only singleton methods)
575
592
n =
576
- any ( SsaSelfDefinitionNode self |
593
+ any ( SelfLocalSourceNode self |
577
594
exists ( MethodBase m |
578
595
selfInMethod ( self .getVariable ( ) , m , tp ) and
579
596
not m instanceof SingletonMethod and
@@ -607,10 +624,10 @@ private DataFlow::Node trackInstance(Module tp, boolean exact, TypeTracker t) {
607
624
m = resolveConstantReadAccess ( result .asExpr ( ) .getExpr ( ) )
608
625
or
609
626
// needed for e.g. `self.include`
610
- selfInModule ( result .( SsaSelfDefinitionNode ) .getVariable ( ) , m )
627
+ selfInModule ( result .( SelfLocalSourceNode ) .getVariable ( ) , m )
611
628
or
612
629
// needed for e.g. `self.puts`
613
- selfInMethod ( result .( SsaSelfDefinitionNode ) .getVariable ( ) , any ( SingletonMethod sm ) , m )
630
+ selfInMethod ( result .( SelfLocalSourceNode ) .getVariable ( ) , any ( SingletonMethod sm ) , m )
614
631
)
615
632
)
616
633
or
@@ -970,7 +987,7 @@ private DataFlow::Node trackSingletonMethodOnInstance(MethodBase method, string
970
987
/** Holds if a `self` access may be the receiver of `call` directly inside module `m`. */
971
988
pragma [ nomagic]
972
989
private predicate selfInModuleFlowsToMethodCallReceiver ( RelevantCall call , Module m , string method ) {
973
- exists ( SsaSelfDefinitionNode self |
990
+ exists ( SelfLocalSourceNode self |
974
991
flowsToMethodCallReceiver ( call , self , method ) and
975
992
selfInModule ( self .getVariable ( ) , m )
976
993
)
@@ -984,7 +1001,7 @@ pragma[nomagic]
984
1001
private predicate selfInSingletonMethodFlowsToMethodCallReceiver (
985
1002
RelevantCall call , Module m , string method
986
1003
) {
987
- exists ( SsaSelfDefinitionNode self , MethodBase caller |
1004
+ exists ( SelfLocalSourceNode self , MethodBase caller |
988
1005
flowsToMethodCallReceiver ( call , self , method ) and
989
1006
selfInMethod ( self .getVariable ( ) , caller , m ) and
990
1007
singletonMethod ( caller , _, _)
@@ -1062,10 +1079,13 @@ private CfgScope getTargetSingleton(RelevantCall call, string method) {
1062
1079
*/
1063
1080
pragma [ nomagic]
1064
1081
private 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
1067
1084
) {
1068
- exists ( ParameterNodeImpl p , ParameterPosition ppos , ArgumentPosition apos |
1085
+ exists (
1086
+ ParameterNodeImpl p , SsaDefinitionExtNode paramDef , ParameterPosition ppos ,
1087
+ ArgumentPosition apos
1088
+ |
1069
1089
// the receiver of `call` references `p`
1070
1090
exists ( DataFlow:: Node receiver |
1071
1091
LocalFlow:: localFlowSsaParamInput ( p , paramDef ) and
@@ -1106,7 +1126,7 @@ private predicate mayBenefitFromCallContextInitialize(
1106
1126
RelevantCall ctx , RelevantCall new , DataFlow:: Node arg , Callable encl , Module tp , string name
1107
1127
) {
1108
1128
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
1110
1130
source = trackModuleAccess ( tp ) and
1111
1131
name = "initialize" and
1112
1132
exists ( lookupMethod ( tp , name ) )
@@ -1127,7 +1147,7 @@ private predicate mayBenefitFromCallContextInstance(
1127
1147
string name
1128
1148
) {
1129
1149
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 ,
1131
1151
pragma [ only_bind_into ] ( name ) ) and
1132
1152
source = trackInstance ( tp , exact ) and
1133
1153
exists ( lookupMethod ( tp , pragma [ only_bind_into ] ( name ) ) )
@@ -1148,7 +1168,7 @@ private predicate mayBenefitFromCallContextSingleton(
1148
1168
string name
1149
1169
) {
1150
1170
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 ,
1152
1172
encl , pragma [ only_bind_into ] ( name ) ) and
1153
1173
exists ( lookupSingletonMethod ( tp , pragma [ only_bind_into ] ( name ) , exact ) )
1154
1174
|
@@ -1216,21 +1236,18 @@ DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
1216
1236
or
1217
1237
// `ctx` cannot provide a type bound, and the receiver of the call is `self`;
1218
1238
// 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 |
1223
1240
call0 = call .asCall ( ) and
1224
1241
ctx0 = ctx .asCall ( ) and
1225
- argMustFlowToReceiver ( ctx0 , _, arg , self , call0 , _, name ) and
1242
+ argMustFlowToReceiver ( ctx0 , _, arg , call0 , _, name ) and
1226
1243
not mayBenefitFromCallContextInitialize ( ctx0 , call0 , arg , _, _, _) and
1227
1244
not mayBenefitFromCallContextInstance ( ctx0 , call0 , arg , _, _, _, name ) and
1228
1245
not mayBenefitFromCallContextSingleton ( ctx0 , call0 , arg , _, _, _, name ) and
1229
1246
result .asCallable ( ) = viableSourceCallable ( call0 )
1230
1247
)
1231
1248
or
1232
1249
// library calls should always be able to resolve
1233
- argMustFlowToReceiver ( ctx .asCall ( ) , _, _, _ , call .asCall ( ) , _, _) and
1250
+ argMustFlowToReceiver ( ctx .asCall ( ) , _, _, call .asCall ( ) , _, _) and
1234
1251
result = viableLibraryCallable ( call )
1235
1252
)
1236
1253
}
0 commit comments