Skip to content

Commit d0f7052

Browse files
committed
Java: Support instanceof disjunction in union type flow.
1 parent 686e03e commit d0f7052

File tree

1 file changed

+39
-2
lines changed

1 file changed

+39
-2
lines changed

java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
653684
private 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) {
694727
pragma[nomagic]
695728
private 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

Comments
 (0)