@@ -237,7 +237,7 @@ class NormalCall extends DataFlowCall, TNormalCall {
237237 * need to track the `View` instance (2) into the receiver of the adjusted method
238238 * call, in order to figure out that the call target is in fact `view.html.erb`.
239239 */
240- private module ViewComponentRenderModeling {
240+ module ViewComponentRenderModeling {
241241 private import codeql.ruby.frameworks.ViewComponent
242242
243243 private class RenderMethod extends SummarizedCallable , LibraryCallableToIncludeInTypeTracking {
@@ -333,7 +333,7 @@ private predicate selfInModule(SelfVariable self, Module m) {
333333
334334/** Holds if `self` belongs to method `method` inside module `m`. */
335335pragma [ nomagic]
336- private predicate selfInMethod ( SelfVariable self , MethodBase method , Module m ) {
336+ predicate selfInMethod ( SelfVariable self , MethodBase method , Module m ) {
337337 exists ( ModuleBase encl |
338338 method = self .getDeclaringScope ( ) and
339339 encl = method .getEnclosingModule ( ) and
@@ -343,67 +343,6 @@ private predicate selfInMethod(SelfVariable self, MethodBase method, Module m) {
343343 )
344344}
345345
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-
407346/** Holds if `new` is a user-defined `self.new` method. */
408347predicate isUserDefinedNew ( SingletonMethod new ) {
409348 exists ( Expr object | singletonMethod ( new , "new" , object ) |
@@ -638,7 +577,7 @@ private predicate hasUserDefinedNew(Module m) {
638577 * `self.new` on `m`.
639578 */
640579pragma [ nomagic]
641- private predicate isStandardNewCall ( RelevantCall new , Module m , boolean exact ) {
580+ predicate isStandardNewCall ( RelevantCall new , Module m , boolean exact ) {
642581 exists ( DataFlow:: LocalSourceNode sourceNode |
643582 flowsToMethodCallReceiver ( TNormalCall ( new ) , sourceNode , "new" ) and
644583 // `m` should not have a user-defined `self.new` method
@@ -667,106 +606,11 @@ private predicate localFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo,
667606}
668607
669608private 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-
765609 newtype State = additional MkState ( Module m , Boolean exact )
766610
767611 predicate start ( DataFlow:: Node start , State state ) {
768612 exists ( Module tp , boolean exact | state = MkState ( tp , exact ) |
769- isInstance ( start , tp , exact )
613+ TypeInference :: hasType ( start , tp , exact )
770614 or
771615 exists ( Module m |
772616 ( if m .isClass ( ) then tp = Module:: TResolved ( "Class" ) else tp = Module:: TResolved ( "Module" ) ) and
@@ -784,15 +628,20 @@ private module TrackInstanceInput implements CallGraphConstruction::InputSig {
784628 )
785629 }
786630
631+ pragma [ nomagic]
632+ private predicate hasAdjacentTypeCheckedRead ( DataFlow:: Node node ) {
633+ TypeInference:: hasAdjacentTypeCheckedRead ( node .asExpr ( ) , _)
634+ }
635+
787636 pragma [ nomagic]
788637 predicate stepNoCall ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo , StepSummary summary ) {
789638 smallStepNoCall ( nodeFrom , nodeTo , summary )
790639 or
791640 // We exclude steps into type checked variables. For those, we instead rely on the
792641 // type being checked against
793642 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 ( ) , _)
796645 }
797646
798647 predicate stepCall ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo , StepSummary summary ) {
0 commit comments