@@ -299,10 +299,7 @@ private Callable viableSourceCallableNonInit(RelevantCall call) {
299
299
not call .getExpr ( ) instanceof YieldCall // handled by `lambdaCreation`/`lambdaCall`
300
300
}
301
301
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 ) }
306
303
307
304
/** Holds if `call` may resolve to the returned source-code method. */
308
305
private Callable viableSourceCallable ( RelevantCall call ) {
@@ -374,9 +371,14 @@ private module Cached {
374
371
*/
375
372
cached
376
373
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 ( ) )
380
382
)
381
383
}
382
384
@@ -481,6 +483,35 @@ private predicate hasUserDefinedNew(Module m) {
481
483
)
482
484
}
483
485
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
+
484
515
/** Holds if `n` is an instance of type `tp`. */
485
516
private predicate isInstance ( DataFlow:: Node n , Module tp , boolean exact ) {
486
517
n .asExpr ( ) .getExpr ( ) instanceof NilLiteral and
@@ -535,27 +566,7 @@ private predicate isInstance(DataFlow::Node n, Module tp, boolean exact) {
535
566
tp = TResolved ( "Proc" ) and
536
567
exact = true
537
568
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 )
559
570
or
560
571
// `self` reference in method or top-level (but not in module or singleton method,
561
572
// where instance methods cannot be called; only singleton methods)
0 commit comments