@@ -294,23 +294,25 @@ private DataFlowCallable viableLibraryCallable(DataFlowCall call) {
294
294
)
295
295
}
296
296
297
- /** Holds if there is a call like `receiver.extend(M)` */
297
+ /** Holds if there is a call like `receiver.extend(M)`. */
298
298
pragma [ nomagic]
299
- private predicate flowsToExtendCall ( DataFlow:: LocalSourceNode receiver , Module m ) {
299
+ private predicate extendCall ( DataFlow:: ExprNode receiver , Module m ) {
300
300
exists ( DataFlow:: CallNode extendCall |
301
301
extendCall .getMethodName ( ) = "extend" and
302
302
exists ( DataFlow:: LocalSourceNode sourceNode | sourceNode .flowsTo ( extendCall .getArgument ( 0 ) ) |
303
303
selfInModule ( sourceNode .( SsaSelfDefinitionNode ) .getVariable ( ) , m ) or
304
304
m = resolveConstantReadAccess ( sourceNode .asExpr ( ) .getExpr ( ) )
305
305
) and
306
- receiver . flowsTo ( extendCall .getReceiver ( ) )
306
+ receiver = extendCall .getReceiver ( )
307
307
)
308
308
}
309
309
310
310
/** Holds if there is a call like `M.extend(N)` */
311
311
pragma [ nomagic]
312
312
private predicate extendCallModule ( Module m , Module n ) {
313
- exists ( DataFlow:: LocalSourceNode receiver | flowsToExtendCall ( receiver , n ) |
313
+ exists ( DataFlow:: LocalSourceNode receiver , DataFlow:: ExprNode e |
314
+ receiver .flowsTo ( e ) and extendCall ( e , n )
315
+ |
314
316
selfInModule ( receiver .( SsaSelfDefinitionNode ) .getVariable ( ) , m ) or
315
317
m = resolveConstantReadAccess ( receiver .asExpr ( ) .getExpr ( ) )
316
318
)
@@ -373,14 +375,7 @@ private module Cached {
373
375
// ```
374
376
exists ( DataFlow:: Node receiver |
375
377
methodCall ( call , receiver , method ) and
376
- (
377
- receiver = trackSingletonMethodOnInstance ( result , method )
378
- or
379
- exists ( Module m |
380
- flowsToExtendCall ( any ( DataFlow:: LocalSourceNode n | n .flowsTo ( receiver ) ) , m ) and
381
- result = lookupMethod ( m , pragma [ only_bind_into ] ( method ) )
382
- )
383
- )
378
+ receiver = trackSingletonMethodOnInstance ( result , method )
384
379
)
385
380
or
386
381
// singleton method defined on a module
@@ -394,14 +389,7 @@ private module Cached {
394
389
// ```
395
390
exists ( DataFlow:: Node sourceNode , Module m |
396
391
flowsToMethodCall ( call , sourceNode , method ) and
397
- (
398
- singletonMethodOnModule ( result , method , m )
399
- or
400
- exists ( Module other |
401
- extendCallModule ( m , other ) and
402
- result = lookupMethod ( other , pragma [ only_bind_into ] ( method ) )
403
- )
404
- )
392
+ singletonMethodOnModule ( result , method , m )
405
393
|
406
394
// ```rb
407
395
// def C.singleton; end # <- result
@@ -717,6 +705,12 @@ private predicate flowsToSingletonMethodObject(
717
705
* class << c
718
706
* def m6; end # not included
719
707
* end
708
+ *
709
+ * module M
710
+ * def instance; end # included in `N` via `extend` call below
711
+ * end
712
+ * N.extend(M)
713
+ * N.instance
720
714
* ```
721
715
*/
722
716
pragma [ nomagic]
@@ -727,6 +721,11 @@ private predicate singletonMethodOnModule(MethodBase method, string name, Module
727
721
)
728
722
or
729
723
flowsToSingletonMethodObject ( trackModuleAccess ( m ) , method , name )
724
+ or
725
+ exists ( Module other |
726
+ extendCallModule ( m , other ) and
727
+ method = lookupMethod ( other , name )
728
+ )
730
729
}
731
730
732
731
/**
@@ -753,6 +752,11 @@ private predicate singletonMethodOnModule(MethodBase method, string name, Module
753
752
* class << c
754
753
* def m6; end # included
755
754
* end
755
+ *
756
+ * module M
757
+ * def instance; end # included in `c` via `extend` call below
758
+ * end
759
+ * c.extend(M)
756
760
* ```
757
761
*/
758
762
pragma [ nomagic]
@@ -761,6 +765,12 @@ predicate singletonMethodOnInstance(MethodBase method, string name, Expr object)
761
765
not selfInModule ( object .( SelfVariableReadAccess ) .getVariable ( ) , _) and
762
766
// cannot use `trackModuleAccess` because of negative recursion
763
767
not exists ( resolveConstantReadAccess ( object ) )
768
+ or
769
+ exists ( DataFlow:: ExprNode receiver , Module other |
770
+ extendCall ( receiver , other ) and
771
+ object = receiver .getExprNode ( ) .getExpr ( ) and
772
+ method = lookupMethod ( other , name )
773
+ )
764
774
}
765
775
766
776
/**
0 commit comments