@@ -650,6 +650,37 @@ private predicate unionTypeFlowBaseCand(TypeFlowNode n, RefType t, boolean exact
650650 )
651651}
652652
653+ /**
654+ * Holds if `ioe` checks `v`, its true-successor is `bb`, and `bb` has 2 or more
655+ * predecessors.
656+ */
657+ private predicate instanceofDisjunct ( InstanceOfExpr ioe , BasicBlock bb , BaseSsaVariable v ) {
658+ ioe .getExpr ( ) = v .getAUse ( ) and
659+ strictcount ( bb .getABBPredecessor ( ) ) > 1 and
660+ exists ( ConditionBlock cb | cb .getCondition ( ) = ioe and cb .getTestSuccessor ( true ) = bb )
661+ }
662+
663+ /** Holds if `bb` is disjunctively guarded by two or more `instanceof` tests on `v`. */
664+ private predicate instanceofDisjunction ( BasicBlock bb , BaseSsaVariable v ) {
665+ strictcount ( InstanceOfExpr ioe | instanceofDisjunct ( ioe , bb , v ) ) =
666+ strictcount ( bb .getABBPredecessor ( ) )
667+ }
668+
669+ /**
670+ * Holds if `n` is a value that is guarded by a disjunction of
671+ * `instanceof t_i` where `t` is one of those `t_i`.
672+ */
673+ private predicate instanceofDisjunctionGuarded ( TypeFlowNode n , RefType t ) {
674+ exists ( BasicBlock bb , InstanceOfExpr ioe , BaseSsaVariable v , VarAccess va |
675+ instanceofDisjunction ( bb , v ) and
676+ bb .bbDominates ( va .getBasicBlock ( ) ) and
677+ va = v .getAUse ( ) and
678+ instanceofDisjunct ( ioe , bb , v ) and
679+ t = ioe .getCheckedType ( ) and
680+ n .asExpr ( ) = va
681+ )
682+ }
683+
653684private module HasUnionTypePropagation implements TypePropagation {
654685 class Typ = Unit ;
655686
@@ -681,6 +712,8 @@ private predicate hasUnionTypeFlow(TypeFlowNode n) {
681712 )
682713 or
683714 exists ( TypeFlowNode mid | step ( mid , n ) and hasUnionTypeFlow ( mid ) )
715+ or
716+ instanceofDisjunctionGuarded ( n , _)
684717 )
685718}
686719
@@ -694,8 +727,12 @@ private RefType getTypeBound(TypeFlowNode n) {
694727pragma [ nomagic]
695728private predicate unionTypeFlow0 ( TypeFlowNode n , RefType t , boolean exact ) {
696729 hasUnionTypeFlow ( n ) and
697- exists ( TypeFlowNode mid | anyStep ( mid , n ) |
698- unionTypeFlowBaseCand ( mid , t , exact ) or unionTypeFlow ( mid , t , exact )
730+ (
731+ exists ( TypeFlowNode mid | anyStep ( mid , n ) |
732+ unionTypeFlowBaseCand ( mid , t , exact ) or unionTypeFlow ( mid , t , exact )
733+ )
734+ or
735+ instanceofDisjunctionGuarded ( n , t ) and exact = false
699736 )
700737}
701738
0 commit comments