@@ -229,7 +229,7 @@ private predicate selfInModule(SelfVariable self, Module m) {
229229
230230/** Holds if `self` belongs to method `method` inside module `m`. */
231231pragma [ nomagic]
232- private predicate selfInMethod ( SelfVariable self , MethodBase method , Module m ) {
232+ predicate selfInMethod ( SelfVariable self , MethodBase method , Module m ) {
233233 exists ( ModuleBase encl |
234234 method = self .getDeclaringScope ( ) and
235235 encl = method .getEnclosingModule ( ) and
@@ -239,64 +239,6 @@ private predicate selfInMethod(SelfVariable self, MethodBase method, Module m) {
239239 )
240240}
241241
242- /** Holds if `self` belongs to the top-level. */
243- pragma [ nomagic]
244- private predicate selfInToplevel ( SelfVariable self , Module m ) {
245- self .getDeclaringScope ( ) instanceof Toplevel and
246- m = TResolved ( "Object" )
247- }
248-
249- /**
250- * Holds if SSA definition `def` belongs to a variable introduced via pattern
251- * matching on type `m`. For example, in
252- *
253- * ```rb
254- * case object
255- * in C => c then c.foo
256- * end
257- * ```
258- *
259- * the SSA definition for `c` is introduced by matching on `C`.
260- */
261- private predicate asModulePattern ( SsaDefinitionExtNode def , Module m ) {
262- exists ( AsPattern ap |
263- m = resolveConstantReadAccess ( ap .getPattern ( ) ) and
264- def .getDefinitionExt ( ) .( Ssa:: WriteDefinition ) .getWriteAccess ( ) .getAstNode ( ) =
265- ap .getVariableAccess ( )
266- )
267- }
268-
269- /**
270- * Holds if `read1` and `read2` are adjacent reads of SSA definition `def`,
271- * and `read2` is checked to have type `m`. For example, in
272- *
273- * ```rb
274- * case object
275- * when C then object.foo
276- * end
277- * ```
278- *
279- * the two reads of `object` are adjacent, and the second is checked to have type `C`.
280- */
281- private predicate hasAdjacentTypeCheckedReads (
282- Ssa:: Definition def , CfgNodes:: ExprCfgNode read1 , CfgNodes:: ExprCfgNode read2 , Module m
283- ) {
284- exists (
285- CfgNodes:: ExprCfgNode pattern , ConditionBlock cb , CfgNodes:: ExprNodes:: CaseExprCfgNode case
286- |
287- m = resolveConstantReadAccess ( pattern .getExpr ( ) ) and
288- cb .getLastNode ( ) = pattern and
289- cb .controls ( read2 .getBasicBlock ( ) ,
290- any ( SuccessorTypes:: MatchingSuccessor match | match .getValue ( ) = true ) ) and
291- def .hasAdjacentReads ( read1 , read2 ) and
292- case .getValue ( ) = read1
293- |
294- pattern = case .getBranch ( _) .( CfgNodes:: ExprNodes:: WhenClauseCfgNode ) .getPattern ( _)
295- or
296- pattern = case .getBranch ( _) .( CfgNodes:: ExprNodes:: InClauseCfgNode ) .getPattern ( )
297- )
298- }
299-
300242/** Holds if `new` is a user-defined `self.new` method. */
301243predicate isUserDefinedNew ( SingletonMethod new ) {
302244 exists ( Expr object | singletonMethod ( new , "new" , object ) |
@@ -507,7 +449,7 @@ private predicate hasUserDefinedNew(Module m) {
507449 * `self.new` on `m`.
508450 */
509451pragma [ nomagic]
510- private predicate isStandardNewCall ( RelevantCall new , Module m , boolean exact ) {
452+ predicate isStandardNewCall ( RelevantCall new , Module m , boolean exact ) {
511453 exists ( DataFlow:: LocalSourceNode sourceNode |
512454 flowsToMethodCallReceiver ( new , sourceNode , "new" ) and
513455 // `m` should not have a user-defined `self.new` method
@@ -537,105 +479,15 @@ private predicate localFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo,
537479
538480private module TrackInstanceInput implements CallGraphConstruction:: InputSig {
539481 pragma [ nomagic]
540- private predicate isInstanceNoCall ( DataFlow:: Node n , Module tp , boolean exact ) {
541- n .asExpr ( ) .getExpr ( ) instanceof NilLiteral and
542- tp = TResolved ( "NilClass" ) and
543- exact = true
544- or
545- n .asExpr ( ) .getExpr ( ) .( BooleanLiteral ) .isFalse ( ) and
546- tp = TResolved ( "FalseClass" ) and
547- exact = true
548- or
549- n .asExpr ( ) .getExpr ( ) .( BooleanLiteral ) .isTrue ( ) and
550- tp = TResolved ( "TrueClass" ) and
551- exact = true
552- or
553- n .asExpr ( ) .getExpr ( ) instanceof IntegerLiteral and
554- tp = TResolved ( "Integer" ) and
555- exact = true
556- or
557- n .asExpr ( ) .getExpr ( ) instanceof FloatLiteral and
558- tp = TResolved ( "Float" ) and
559- exact = true
560- or
561- n .asExpr ( ) .getExpr ( ) instanceof RationalLiteral and
562- tp = TResolved ( "Rational" ) and
563- exact = true
564- or
565- n .asExpr ( ) .getExpr ( ) instanceof ComplexLiteral and
566- tp = TResolved ( "Complex" ) and
567- exact = true
568- or
569- n .asExpr ( ) .getExpr ( ) instanceof StringlikeLiteral and
570- tp = TResolved ( "String" ) and
571- exact = true
572- or
573- n .asExpr ( ) instanceof CfgNodes:: ExprNodes:: ArrayLiteralCfgNode and
574- tp = TResolved ( "Array" ) and
575- exact = true
576- or
577- n .asExpr ( ) instanceof CfgNodes:: ExprNodes:: HashLiteralCfgNode and
578- tp = TResolved ( "Hash" ) and
579- exact = true
580- or
581- n .asExpr ( ) .getExpr ( ) instanceof MethodBase and
582- tp = TResolved ( "Symbol" ) and
583- exact = true
584- or
585- n .asParameter ( ) instanceof BlockParameter and
586- tp = TResolved ( "Proc" ) and
587- exact = true
588- or
589- n .asExpr ( ) .getExpr ( ) instanceof Lambda and
590- tp = TResolved ( "Proc" ) and
591- exact = true
592- or
593- // `self` reference in method or top-level (but not in module or singleton method,
594- // where instance methods cannot be called; only singleton methods)
595- n =
596- any ( SelfLocalSourceNode self |
597- exists ( MethodBase m |
598- selfInMethod ( self .getVariable ( ) , m , tp ) and
599- not m instanceof SingletonMethod and
600- if m .getEnclosingModule ( ) instanceof Toplevel then exact = true else exact = false
601- )
602- or
603- selfInToplevel ( self .getVariable ( ) , tp ) and
604- exact = true
605- )
606- or
607- // `in C => c then c.foo`
608- asModulePattern ( n , tp ) and
609- exact = false
610- or
611- // `case object when C then object.foo`
612- hasAdjacentTypeCheckedReads ( _, _, n .asExpr ( ) , tp ) and
613- exact = false
614- }
615-
616- pragma [ nomagic]
617- private predicate isInstanceCall ( DataFlow:: Node n , Module tp , boolean exact ) {
618- isStandardNewCall ( n .asExpr ( ) , tp , exact )
619- }
620-
621- /** Holds if `n` is an instance of type `tp`. */
622- pragma [ inline]
623- private predicate isInstance ( DataFlow:: Node n , Module tp , boolean exact ) {
624- isInstanceNoCall ( n , tp , exact )
625- or
626- isInstanceCall ( n , tp , exact )
627- }
628-
629- pragma [ nomagic]
630- private predicate hasAdjacentTypeCheckedReads ( DataFlow:: Node node ) {
631- hasAdjacentTypeCheckedReads ( _, _, node .asExpr ( ) , _)
482+ private predicate hasAdjacentTypeCheckedRead ( DataFlow:: Node node ) {
483+ TypeInference:: hasAdjacentTypeCheckedRead ( node .asExpr ( ) , _)
632484 }
633485
634486 newtype State = additional MkState ( Module m , Boolean exact )
635487
636488 predicate start ( DataFlow:: Node start , State state ) {
637489 exists ( Module tp , boolean exact | state = MkState ( tp , exact ) |
638- isInstance ( start , tp , exact )
490+ TypeInference :: hasType ( start , tp , exact )
639491 or
640492 exists ( Module m |
641493 ( if m .isClass ( ) then tp = TResolved ( "Class" ) else tp = TResolved ( "Module" ) ) and
@@ -663,8 +515,8 @@ private module TrackInstanceInput implements CallGraphConstruction::InputSig {
663515 // We exclude steps into type checked variables. For those, we instead rely on the
664516 // type being checked against
665517 localFlowStep ( nodeFrom , nodeTo , summary ) and
666- not hasAdjacentTypeCheckedReads ( nodeTo ) and
667- not asModulePattern ( nodeTo , _)
518+ not hasAdjacentTypeCheckedRead ( nodeTo ) and
519+ not TypeInference :: asModulePattern ( nodeTo . ( SsaDefinitionExtNode ) . getDefinitionExt ( ) , _)
668520 }
669521
670522 predicate stepCall ( DataFlow:: Node nodeFrom , DataFlow:: Node nodeTo , StepSummary summary ) {
0 commit comments