@@ -650,6 +650,37 @@ private predicate unionTypeFlowBaseCand(TypeFlowNode n, RefType t, boolean exact
650
650
)
651
651
}
652
652
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
+
653
684
private module HasUnionTypePropagation implements TypePropagation {
654
685
class Typ = Unit ;
655
686
@@ -681,6 +712,8 @@ private predicate hasUnionTypeFlow(TypeFlowNode n) {
681
712
)
682
713
or
683
714
exists ( TypeFlowNode mid | step ( mid , n ) and hasUnionTypeFlow ( mid ) )
715
+ or
716
+ instanceofDisjunctionGuarded ( n , _)
684
717
)
685
718
}
686
719
@@ -694,8 +727,12 @@ private RefType getTypeBound(TypeFlowNode n) {
694
727
pragma [ nomagic]
695
728
private predicate unionTypeFlow0 ( TypeFlowNode n , RefType t , boolean exact ) {
696
729
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
699
736
)
700
737
}
701
738
0 commit comments