@@ -558,15 +558,19 @@ DataFlowCallable nodeGetEnclosingCallable(Node node) {
558558
559559newtype TDataFlowType =
560560 TFunctionType ( Function f ) or
561+ TInstanceType ( DataFlow:: ClassNode cls ) or
561562 TAnyType ( )
562563
563564class DataFlowType extends TDataFlowType {
564565 string toDebugString ( ) {
565- this instanceof TFunctionType and
566566 result =
567567 "TFunctionType(" + this .asFunction ( ) .toString ( ) + ") at line " +
568568 this .asFunction ( ) .getLocation ( ) .getStartLine ( )
569569 or
570+ result =
571+ "TInstanceType(" + this .asInstanceOfClass ( ) .toString ( ) + ") at line " +
572+ this .asInstanceOfClass ( ) .getLocation ( ) .getStartLine ( )
573+ or
570574 this instanceof TAnyType and result = "TAnyType"
571575 }
572576
@@ -575,13 +579,25 @@ class DataFlowType extends TDataFlowType {
575579 }
576580
577581 Function asFunction ( ) { this = TFunctionType ( result ) }
582+
583+ DataFlow:: ClassNode asInstanceOfClass ( ) { this = TInstanceType ( result ) }
584+ }
585+
586+ private predicate typeStrongerThan1 ( DataFlowType t1 , DataFlowType t2 ) {
587+ // 't1' is a subclass of 't2'
588+ t1 .asInstanceOfClass ( ) = t2 .asInstanceOfClass ( ) .getADirectSubClass ( )
578589}
579590
580591/**
581592 * Holds if `t1` is strictly stronger than `t2`.
582593 */
583594predicate typeStrongerThan ( DataFlowType t1 , DataFlowType t2 ) {
584- t1 instanceof TFunctionType and t2 = TAnyType ( )
595+ typeStrongerThan1 ( t1 , t2 )
596+ or
597+ // Ensure all types are transitively stronger than 'any'
598+ not typeStrongerThan1 ( t1 , _) and
599+ not t1 = TAnyType ( ) and
600+ t2 = TAnyType ( )
585601}
586602
587603private DataFlowType getPreciseType ( Node node ) {
@@ -590,6 +606,9 @@ private DataFlowType getPreciseType(Node node) {
590606 result = TFunctionType ( f )
591607 )
592608 or
609+ result .asInstanceOfClass ( ) =
610+ unique( DataFlow:: ClassNode cls | cls .getAnInstanceReference ( ) .getALocalUse ( ) = node )
611+ or
593612 result = getPreciseType ( node .getImmediatePredecessor ( ) )
594613 or
595614 result = getPreciseType ( node .( PostUpdateNode ) .getPreUpdateNode ( ) )
@@ -683,18 +702,27 @@ predicate neverSkipInPathGraph(Node node) {
683702string ppReprType ( DataFlowType t ) { none ( ) }
684703
685704pragma [ inline]
686- private predicate compatibleTypesNonSymRefl ( DataFlowType t1 , DataFlowType t2 ) {
705+ private predicate compatibleTypesWithAny ( DataFlowType t1 , DataFlowType t2 ) {
687706 t1 != TAnyType ( ) and
688707 t2 = TAnyType ( )
689708}
690709
710+ pragma [ nomagic]
711+ private predicate compatibleTypes1 ( DataFlowType t1 , DataFlowType t2 ) {
712+ t1 .asInstanceOfClass ( ) .getADirectSubClass + ( ) = t2 .asInstanceOfClass ( )
713+ }
714+
691715pragma [ inline]
692716predicate compatibleTypes ( DataFlowType t1 , DataFlowType t2 ) {
693717 t1 = t2
694718 or
695- compatibleTypesNonSymRefl ( t1 , t2 )
719+ compatibleTypesWithAny ( t1 , t2 )
720+ or
721+ compatibleTypesWithAny ( t2 , t1 )
722+ or
723+ compatibleTypes1 ( t1 , t2 )
696724 or
697- compatibleTypesNonSymRefl ( t2 , t1 )
725+ compatibleTypes1 ( t2 , t1 )
698726}
699727
700728predicate forceHighPrecision ( Content c ) { none ( ) }
0 commit comments