@@ -237,7 +237,7 @@ class NormalCall extends DataFlowCall, TNormalCall {
237
237
* need to track the `View` instance (2) into the receiver of the adjusted method
238
238
* call, in order to figure out that the call target is in fact `view.html.erb`.
239
239
*/
240
- private module ViewComponentRenderModeling {
240
+ module ViewComponentRenderModeling {
241
241
private import codeql.ruby.frameworks.ViewComponent
242
242
243
243
private class RenderMethod extends SummarizedCallable , LibraryCallableToIncludeInTypeTracking {
@@ -333,7 +333,7 @@ private predicate selfInModule(SelfVariable self, Module m) {
333
333
334
334
/** Holds if `self` belongs to method `method` inside module `m`. */
335
335
pragma [ nomagic]
336
- private predicate selfInMethod ( SelfVariable self , MethodBase method , Module m ) {
336
+ predicate selfInMethod ( SelfVariable self , MethodBase method , Module m ) {
337
337
exists ( ModuleBase encl |
338
338
method = self .getDeclaringScope ( ) and
339
339
encl = method .getEnclosingModule ( ) and
@@ -343,67 +343,6 @@ private predicate selfInMethod(SelfVariable self, MethodBase method, Module m) {
343
343
)
344
344
}
345
345
346
- /** Holds if `self` belongs to the top-level. */
347
- pragma [ nomagic]
348
- private predicate selfInToplevel ( SelfVariable self , Module m ) {
349
- ViewComponentRenderModeling:: selfInErbToplevel ( self , m )
350
- or
351
- not ViewComponentRenderModeling:: selfInErbToplevel ( self , _) and
352
- self .getDeclaringScope ( ) instanceof Toplevel and
353
- m = Module:: TResolved ( "Object" )
354
- }
355
-
356
- /**
357
- * Holds if SSA definition `def` belongs to a variable introduced via pattern
358
- * matching on type `m`. For example, in
359
- *
360
- * ```rb
361
- * case object
362
- * in C => c then c.foo
363
- * end
364
- * ```
365
- *
366
- * the SSA definition for `c` is introduced by matching on `C`.
367
- */
368
- private predicate asModulePattern ( SsaDefinitionExtNode def , Module m ) {
369
- exists ( AsPattern ap |
370
- m = Module:: resolveConstantReadAccess ( ap .getPattern ( ) ) and
371
- def .getDefinitionExt ( ) .( Ssa:: WriteDefinition ) .getWriteAccess ( ) .getAstNode ( ) =
372
- ap .getVariableAccess ( )
373
- )
374
- }
375
-
376
- /**
377
- * Holds if `read1` and `read2` are adjacent reads of SSA definition `def`,
378
- * and `read2` is checked to have type `m`. For example, in
379
- *
380
- * ```rb
381
- * case object
382
- * when C then object.foo
383
- * end
384
- * ```
385
- *
386
- * the two reads of `object` are adjacent, and the second is checked to have type `C`.
387
- */
388
- private predicate hasAdjacentTypeCheckedReads (
389
- Ssa:: Definition def , CfgNodes:: ExprCfgNode read1 , CfgNodes:: ExprCfgNode read2 , Module m
390
- ) {
391
- exists (
392
- CfgNodes:: ExprCfgNode pattern , ConditionBlock cb , CfgNodes:: ExprNodes:: CaseExprCfgNode case
393
- |
394
- m = Module:: resolveConstantReadAccess ( pattern .getExpr ( ) ) and
395
- cb .getLastNode ( ) = pattern and
396
- cb .controls ( read2 .getBasicBlock ( ) ,
397
- any ( SuccessorTypes:: MatchingSuccessor match | match .getValue ( ) = true ) ) and
398
- def .hasAdjacentReads ( read1 , read2 ) and
399
- case .getValue ( ) = read1
400
- |
401
- pattern = case .getBranch ( _) .( CfgNodes:: ExprNodes:: WhenClauseCfgNode ) .getPattern ( _)
402
- or
403
- pattern = case .getBranch ( _) .( CfgNodes:: ExprNodes:: InClauseCfgNode ) .getPattern ( )
404
- )
405
- }
406
-
407
346
/** Holds if `new` is a user-defined `self.new` method. */
408
347
predicate isUserDefinedNew ( SingletonMethod new ) {
409
348
exists ( Expr object | singletonMethod ( new , "new" , object ) |
@@ -638,7 +577,7 @@ private predicate hasUserDefinedNew(Module m) {
638
577
* `self.new` on `m`.
639
578
*/
640
579
pragma [ nomagic]
641
- private predicate isStandardNewCall ( RelevantCall new , Module m , boolean exact ) {
580
+ predicate isStandardNewCall ( RelevantCall new , Module m , boolean exact ) {
642
581
exists ( DataFlow:: LocalSourceNode sourceNode |
643
582
flowsToMethodCallReceiver ( TNormalCall ( new ) , sourceNode , "new" ) and
644
583
// `m` should not have a user-defined `self.new` method
@@ -667,106 +606,11 @@ private predicate localFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo,
667
606
}
668
607
669
608
private module TrackInstanceInput implements CallGraphConstruction:: InputSig {
670
- pragma [ nomagic]
671
- private predicate isInstanceNoCall ( DataFlow:: Node n , Module tp , boolean exact ) {
672
- n .asExpr ( ) .getExpr ( ) instanceof NilLiteral and
673
- tp = Module:: TResolved ( "NilClass" ) and
674
- exact = true
675
- or
676
- n .asExpr ( ) .getExpr ( ) .( BooleanLiteral ) .isFalse ( ) and
677
- tp = Module:: TResolved ( "FalseClass" ) and
678
- exact = true
679
- or
680
- n .asExpr ( ) .getExpr ( ) .( BooleanLiteral ) .isTrue ( ) and
681
- tp = Module:: TResolved ( "TrueClass" ) and
682
- exact = true
683
- or
684
- n .asExpr ( ) .getExpr ( ) instanceof IntegerLiteral and
685
- tp = Module:: TResolved ( "Integer" ) and
686
- exact = true
687
- or
688
- n .asExpr ( ) .getExpr ( ) instanceof FloatLiteral and
689
- tp = Module:: TResolved ( "Float" ) and
690
- exact = true
691
- or
692
- n .asExpr ( ) .getExpr ( ) instanceof RationalLiteral and
693
- tp = Module:: TResolved ( "Rational" ) and
694
- exact = true
695
- or
696
- n .asExpr ( ) .getExpr ( ) instanceof ComplexLiteral and
697
- tp = Module:: TResolved ( "Complex" ) and
698
- exact = true
699
- or
700
- n .asExpr ( ) .getExpr ( ) instanceof StringlikeLiteral and
701
- tp = Module:: TResolved ( "String" ) and
702
- exact = true
703
- or
704
- n .asExpr ( ) instanceof CfgNodes:: ExprNodes:: ArrayLiteralCfgNode and
705
- tp = Module:: TResolved ( "Array" ) and
706
- exact = true
707
- or
708
- n .asExpr ( ) instanceof CfgNodes:: ExprNodes:: HashLiteralCfgNode and
709
- tp = Module:: TResolved ( "Hash" ) and
710
- exact = true
711
- or
712
- n .asExpr ( ) .getExpr ( ) instanceof MethodBase and
713
- tp = Module:: TResolved ( "Symbol" ) and
714
- exact = true
715
- or
716
- n .asParameter ( ) instanceof BlockParameter and
717
- tp = Module:: TResolved ( "Proc" ) and
718
- exact = true
719
- or
720
- n .asExpr ( ) .getExpr ( ) instanceof Lambda and
721
- tp = Module:: TResolved ( "Proc" ) and
722
- exact = true
723
- or
724
- // `self` reference in method or top-level (but not in module or singleton method,
725
- // where instance methods cannot be called; only singleton methods)
726
- n =
727
- any ( SelfLocalSourceNode self |
728
- exists ( MethodBase m |
729
- selfInMethod ( self .getVariable ( ) , m , tp ) and
730
- not m instanceof SingletonMethod and
731
- if m .getEnclosingModule ( ) instanceof Toplevel then exact = true else exact = false
732
- )
733
- or
734
- selfInToplevel ( self .getVariable ( ) , tp ) and
735
- exact = true
736
- )
737
- or
738
- // `in C => c then c.foo`
739
- asModulePattern ( n , tp ) and
740
- exact = false
741
- or
742
- // `case object when C then object.foo`
743
- hasAdjacentTypeCheckedReads ( _, _, n .asExpr ( ) , tp ) and
744
- exact = false
745
- }
746
-
747
- pragma [ nomagic]
748
- private predicate isInstanceCall ( DataFlow:: Node n , Module tp , boolean exact ) {
749
- isStandardNewCall ( n .asExpr ( ) , tp , exact )
750
- }
751
-
752
- /** Holds if `n` is an instance of type `tp`. */
753
- pragma [ inline]
754
- private predicate isInstance ( DataFlow:: Node n , Module tp , boolean exact ) {
755
- isInstanceNoCall ( n , tp , exact )
756
- or
757
- isInstanceCall ( n , tp , exact )
758
- }
759
-
760
- pragma [ nomagic]
761
- private predicate hasAdjacentTypeCheckedReads ( DataFlow:: Node node ) {
762
- hasAdjacentTypeCheckedReads ( _, _, node .asExpr ( ) , _)
763
- }
764
-
765
609
newtype State = additional MkState ( Module m , Boolean exact )
766
610
767
611
predicate start ( DataFlow:: Node start , State state ) {
768
612
exists ( Module tp , boolean exact | state = MkState ( tp , exact ) |
769
- isInstance ( start , tp , exact )
613
+ TypeInference :: hasType ( start , tp , exact )
770
614
or
771
615
exists ( Module m |
772
616
( if m .isClass ( ) then tp = Module:: TResolved ( "Class" ) else tp = Module:: TResolved ( "Module" ) ) and
@@ -784,15 +628,20 @@ private module TrackInstanceInput implements CallGraphConstruction::InputSig {
784
628
)
785
629
}
786
630
631
+ pragma [ nomagic]
632
+ private predicate hasAdjacentTypeCheckedRead ( DataFlow:: Node node ) {
633
+ TypeInference:: hasAdjacentTypeCheckedRead ( node .asExpr ( ) , _)
634
+ }
635
+
787
636
pragma [ nomagic]
788
637
predicate stepNoCall ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo , StepSummary summary ) {
789
638
smallStepNoCall ( nodeFrom , nodeTo , summary )
790
639
or
791
640
// We exclude steps into type checked variables. For those, we instead rely on the
792
641
// type being checked against
793
642
localFlowStep ( nodeFrom , nodeTo , summary ) and
794
- not hasAdjacentTypeCheckedReads ( nodeTo ) and
795
- not asModulePattern ( nodeTo , _)
643
+ not hasAdjacentTypeCheckedRead ( nodeTo ) and
644
+ not TypeInference :: asModulePattern ( nodeTo . ( SsaDefinitionExtNode ) . getDefinitionExt ( ) , _)
796
645
}
797
646
798
647
predicate stepCall ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo , StepSummary summary ) {
0 commit comments