Type-flow: treat pattern-switch on an array index similar to instanceof

This commit is contained in:
Chris Smowton
2023-10-26 16:38:02 +01:00
parent 7dd4030f51
commit b21aaa75bc
4 changed files with 46 additions and 33 deletions

View File

@@ -178,11 +178,18 @@ class Guard extends ExprParent {
private predicate switchCaseControls(SwitchCase sc, BasicBlock bb) {
exists(BasicBlock caseblock, Expr selector |
selector = sc.getSelectorExpr() and
caseblock.getFirstNode() = sc.getControlFlowNode() and
caseblock.bbDominates(bb) and
forall(ControlFlowNode pred | pred = sc.getControlFlowNode().getAPredecessor() |
pred.(Expr).getParent*() = selector
)
(
if sc instanceof PatternCase
then caseblock.getFirstNode() = sc.(PatternCase).getDecl().getControlFlowNode()
else (
caseblock.getFirstNode() = sc.getControlFlowNode() and
// Check there is no fall-through edge from a previous case:
forall(ControlFlowNode pred | pred = sc.getControlFlowNode().getAPredecessor() |
pred.(Expr).getParent*() = selector
)
)
) and
caseblock.bbDominates(bb)
)
}

View File

@@ -413,45 +413,41 @@ private predicate downcastSuccessor(VarAccess va, RefType t) {
)
}
/**
* Holds if `va` is an access to a value that is guarded by `instanceof t`.
*/
private predicate instanceOfGuarded(VarAccess va, RefType t) {
exists(InstanceOfExpr ioe, BaseSsaVariable v |
ioe.getExpr() = v.getAUse() and
t = ioe.getCheckedType() and
va = v.getAUse() and
guardControls_v1(ioe, va.getBasicBlock(), true)
private Expr getAProbableAlias(Expr e) {
exists(BaseSsaVariable v |
e = v.getAUse() and
result = v.getAUse()
)
or
exists(BaseSsaVariable v1, BaseSsaVariable v2, ArrayAccess aa1, ArrayAccess aa2 |
e = aa1 and
result = aa2 and
aa1.getArray() = v1.getAUse() and
aa1.getIndexExpr() = v2.getAUse() and
aa2.getArray() = v1.getAUse() and
aa2.getIndexExpr() = v2.getAUse()
)
}
/**
* Holds if `aa` is an access to a value that is guarded by `instanceof t`.
* Holds if `e` is an access to a value that is guarded by `instanceof t`.
*/
predicate arrayInstanceOfGuarded(ArrayAccess aa, RefType t) {
exists(InstanceOfExpr ioe, BaseSsaVariable v1, BaseSsaVariable v2, ArrayAccess aa1 |
ioe.getExpr() = aa1 and
private predicate instanceOfGuarded(Expr e, RefType t) {
exists(InstanceOfExpr ioe |
t = ioe.getCheckedType() and
aa1.getArray() = v1.getAUse() and
aa1.getIndexExpr() = v2.getAUse() and
aa.getArray() = v1.getAUse() and
aa.getIndexExpr() = v2.getAUse() and
guardControls_v1(ioe, aa.getBasicBlock(), true)
e = getAProbableAlias(ioe.getExpr()) and
guardControls_v1(ioe, e.getBasicBlock(), true)
)
}
/**
* Holds if `va` is an access to a value that is guarded by `case T t`.
*/
private predicate patternCaseGuarded(VarAccess va, RefType t) {
exists(PatternCase pc, BaseSsaVariable v |
va = v.getAUse() and
(
pc.getSwitch().getExpr() = v.getAUse() or
pc.getSwitchExpr().getExpr() = v.getAUse()
) and
pc.getDecl().getBasicBlock().bbDominates(va.getBasicBlock()) and
t = pc.getDecl().getType()
private predicate patternCaseGuarded(Expr e, RefType t) {
exists(PatternCase pc |
e = getAProbableAlias([pc.getSwitch().getExpr(), pc.getSwitchExpr().getExpr()]) and
guardControls_v1(pc, e.getBasicBlock(), true) and
t = pc.getDecl().getType()
)
}
@@ -478,7 +474,6 @@ private predicate typeFlowBaseCand(TypeFlowNode n, RefType t) {
upcastEnhancedForStmt(n.asSsa(), srctype) or
downcastSuccessor(n.asExpr(), srctype) or
instanceOfGuarded(n.asExpr(), srctype) or
arrayInstanceOfGuarded(n.asExpr(), srctype) or
n.asExpr().(FunctionalExpr).getConstructedType() = srctype or
superAccess(n.asExpr(), srctype) or
patternCaseGuarded(n.asExpr(), srctype)

View File

@@ -92,4 +92,14 @@ public class A extends ArrayList<Long> {
Object r = n;
}
}
public void m9(Object[] xs, int i) {
switch (xs[i]) {
case Integer i2 -> {
Object n = xs[i];
Object r = n;
}
default -> { }
}
}
}

View File

@@ -13,5 +13,6 @@
| A.java:67:22:67:22 | x | Integer | false |
| A.java:70:23:70:24 | x2 | Integer | false |
| A.java:92:18:92:18 | n | Integer | false |
| A.java:100:20:100:20 | n | Integer | false |
| UnionTypes.java:45:7:45:7 | x | Inter | false |
| UnionTypes.java:48:23:48:23 | x | Inter | false |