@@ -299,10 +299,7 @@ private Callable viableSourceCallableNonInit(RelevantCall call) {
299299 not call .getExpr ( ) instanceof YieldCall // handled by `lambdaCreation`/`lambdaCall`
300300}
301301
302- private Callable viableSourceCallableInit ( RelevantCall call ) {
303- result = getInitializeTarget ( call ) and
304- not isUserDefinedNew ( getTarget ( call ) )
305- }
302+ private Callable viableSourceCallableInit ( RelevantCall call ) { result = getInitializeTarget ( call ) }
306303
307304/** Holds if `call` may resolve to the returned source-code method. */
308305private Callable viableSourceCallable ( RelevantCall call ) {
@@ -374,9 +371,14 @@ private module Cached {
374371 */
375372 cached
376373 Method getInitializeTarget ( RelevantCall new ) {
377- exists ( Module m |
378- moduleFlowsToMethodCallReceiver ( new , m , "new" ) and
379- result = lookupMethod ( m , "initialize" )
374+ exists ( Module m , boolean exact |
375+ isStandardNewCall ( new , m , exact ) and
376+ result = lookupMethod ( m , "initialize" , exact ) and
377+ // In the case where `exact = false`, we need to check that there is
378+ // no user-defined `new` method in between `m` and the enclosing module
379+ // of the `initialize` method (`isStandardNewCall` already checks that
380+ // there is no user-defined `new` method in `m` or any of `m`'s ancestors)
381+ not hasUserDefinedNew ( result .getEnclosingModule ( ) .getModule ( ) )
380382 )
381383 }
382384
@@ -481,6 +483,35 @@ private predicate hasUserDefinedNew(Module m) {
481483 )
482484}
483485
486+ /**
487+ * Holds if `new` is a call to `new`, targeting a class of type `m` (or a
488+ * sub class, when `exact = false`), where there is no user-defined
489+ * `self.new` on `m`.
490+ */
491+ pragma [ nomagic]
492+ private predicate isStandardNewCall ( RelevantCall new , Module m , boolean exact ) {
493+ exists ( DataFlow:: LocalSourceNode sourceNode |
494+ flowsToMethodCallReceiver ( new , sourceNode , "new" ) and
495+ // `m` should not have a user-defined `self.new` method
496+ not hasUserDefinedNew ( m )
497+ |
498+ // `C.new`
499+ sourceNode = trackModuleAccess ( m ) and
500+ exact = true
501+ or
502+ // `self.new` inside a module
503+ selfInModule ( sourceNode .( SsaSelfDefinitionNode ) .getVariable ( ) , m ) and
504+ exact = true
505+ or
506+ // `self.new` inside a singleton method
507+ exists ( MethodBase caller |
508+ selfInMethod ( sourceNode .( SsaSelfDefinitionNode ) .getVariable ( ) , caller , m ) and
509+ singletonMethod ( caller , _, _) and
510+ exact = false
511+ )
512+ )
513+ }
514+
484515/** Holds if `n` is an instance of type `tp`. */
485516private predicate isInstance ( DataFlow:: Node n , Module tp , boolean exact ) {
486517 n .asExpr ( ) .getExpr ( ) instanceof NilLiteral and
@@ -535,27 +566,7 @@ private predicate isInstance(DataFlow::Node n, Module tp, boolean exact) {
535566 tp = TResolved ( "Proc" ) and
536567 exact = true
537568 or
538- exists ( RelevantCall call , DataFlow:: LocalSourceNode sourceNode |
539- flowsToMethodCallReceiver ( call , sourceNode , "new" ) and
540- n .asExpr ( ) = call and
541- // `tp` should not have a user-defined `self.new` method
542- not hasUserDefinedNew ( tp )
543- |
544- // `C.new`
545- sourceNode = trackModuleAccess ( tp ) and
546- exact = true
547- or
548- // `self.new` inside a module
549- selfInModule ( sourceNode .( SsaSelfDefinitionNode ) .getVariable ( ) , tp ) and
550- exact = true
551- or
552- // `self.new` inside a singleton method
553- exists ( MethodBase caller |
554- selfInMethod ( sourceNode .( SsaSelfDefinitionNode ) .getVariable ( ) , caller , tp ) and
555- singletonMethod ( caller , _, _) and
556- exact = false
557- )
558- )
569+ isStandardNewCall ( n .asExpr ( ) , tp , exact )
559570 or
560571 // `self` reference in method or top-level (but not in module or singleton method,
561572 // where instance methods cannot be called; only singleton methods)
0 commit comments