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