@@ -294,23 +294,25 @@ private DataFlowCallable viableLibraryCallable(DataFlowCall call) {
294294 )
295295}
296296
297- /** Holds if there is a call like `receiver.extend(M)` */
297+ /** Holds if there is a call like `receiver.extend(M)`. */
298298pragma [ nomagic]
299- private predicate flowsToExtendCall ( DataFlow:: LocalSourceNode receiver , Module m ) {
299+ private predicate extendCall ( DataFlow:: ExprNode receiver , Module m ) {
300300 exists ( DataFlow:: CallNode extendCall |
301301 extendCall .getMethodName ( ) = "extend" and
302302 exists ( DataFlow:: LocalSourceNode sourceNode | sourceNode .flowsTo ( extendCall .getArgument ( 0 ) ) |
303303 selfInModule ( sourceNode .( SsaSelfDefinitionNode ) .getVariable ( ) , m ) or
304304 m = resolveConstantReadAccess ( sourceNode .asExpr ( ) .getExpr ( ) )
305305 ) and
306- receiver . flowsTo ( extendCall .getReceiver ( ) )
306+ receiver = extendCall .getReceiver ( )
307307 )
308308}
309309
310310/** Holds if there is a call like `M.extend(N)` */
311311pragma [ nomagic]
312312private 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+ |
314316 selfInModule ( receiver .( SsaSelfDefinitionNode ) .getVariable ( ) , m ) or
315317 m = resolveConstantReadAccess ( receiver .asExpr ( ) .getExpr ( ) )
316318 )
@@ -373,14 +375,7 @@ private module Cached {
373375 // ```
374376 exists ( DataFlow:: Node receiver |
375377 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 )
384379 )
385380 or
386381 // singleton method defined on a module
@@ -394,14 +389,7 @@ private module Cached {
394389 // ```
395390 exists ( DataFlow:: Node sourceNode , Module m |
396391 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 )
405393 |
406394 // ```rb
407395 // def C.singleton; end # <- result
@@ -717,6 +705,12 @@ private predicate flowsToSingletonMethodObject(
717705 * class << c
718706 * def m6; end # not included
719707 * 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
720714 * ```
721715 */
722716pragma [ nomagic]
@@ -727,6 +721,11 @@ private predicate singletonMethodOnModule(MethodBase method, string name, Module
727721 )
728722 or
729723 flowsToSingletonMethodObject ( trackModuleAccess ( m ) , method , name )
724+ or
725+ exists ( Module other |
726+ extendCallModule ( m , other ) and
727+ method = lookupMethod ( other , name )
728+ )
730729}
731730
732731/**
@@ -753,6 +752,11 @@ private predicate singletonMethodOnModule(MethodBase method, string name, Module
753752 * class << c
754753 * def m6; end # included
755754 * end
755+ *
756+ * module M
757+ * def instance; end # included in `c` via `extend` call below
758+ * end
759+ * c.extend(M)
756760 * ```
757761 */
758762pragma [ nomagic]
@@ -761,6 +765,12 @@ predicate singletonMethodOnInstance(MethodBase method, string name, Expr object)
761765 not selfInModule ( object .( SelfVariableReadAccess ) .getVariable ( ) , _) and
762766 // cannot use `trackModuleAccess` because of negative recursion
763767 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+ )
764774}
765775
766776/**
0 commit comments