Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b21aaa7

Browse files
committed
Type-flow: treat pattern-switch on an array index similar to instanceof
1 parent 7dd4030 commit b21aaa7

4 files changed

Lines changed: 46 additions & 33 deletions

File tree

java/ql/lib/semmle/code/java/controlflow/Guards.qll

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,18 @@ class Guard extends ExprParent {
178178
private predicate switchCaseControls(SwitchCase sc, BasicBlock bb) {
179179
exists(BasicBlock caseblock, Expr selector |
180180
selector = sc.getSelectorExpr() and
181-
caseblock.getFirstNode() = sc.getControlFlowNode() and
182-
caseblock.bbDominates(bb) and
183-
forall(ControlFlowNode pred | pred = sc.getControlFlowNode().getAPredecessor() |
184-
pred.(Expr).getParent*() = selector
185-
)
181+
(
182+
if sc instanceof PatternCase
183+
then caseblock.getFirstNode() = sc.(PatternCase).getDecl().getControlFlowNode()
184+
else (
185+
caseblock.getFirstNode() = sc.getControlFlowNode() and
186+
// Check there is no fall-through edge from a previous case:
187+
forall(ControlFlowNode pred | pred = sc.getControlFlowNode().getAPredecessor() |
188+
pred.(Expr).getParent*() = selector
189+
)
190+
)
191+
) and
192+
caseblock.bbDominates(bb)
186193
)
187194
}
188195

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

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -413,45 +413,41 @@ private predicate downcastSuccessor(VarAccess va, RefType t) {
413413
)
414414
}
415415

416-
/**
417-
* Holds if `va` is an access to a value that is guarded by `instanceof t`.
418-
*/
419-
private predicate instanceOfGuarded(VarAccess va, RefType t) {
420-
exists(InstanceOfExpr ioe, BaseSsaVariable v |
421-
ioe.getExpr() = v.getAUse() and
422-
t = ioe.getCheckedType() and
423-
va = v.getAUse() and
424-
guardControls_v1(ioe, va.getBasicBlock(), true)
416+
private Expr getAProbableAlias(Expr e) {
417+
exists(BaseSsaVariable v |
418+
e = v.getAUse() and
419+
result = v.getAUse()
420+
)
421+
or
422+
exists(BaseSsaVariable v1, BaseSsaVariable v2, ArrayAccess aa1, ArrayAccess aa2 |
423+
e = aa1 and
424+
result = aa2 and
425+
aa1.getArray() = v1.getAUse() and
426+
aa1.getIndexExpr() = v2.getAUse() and
427+
aa2.getArray() = v1.getAUse() and
428+
aa2.getIndexExpr() = v2.getAUse()
425429
)
426430
}
427431

428432
/**
429-
* Holds if `aa` is an access to a value that is guarded by `instanceof t`.
433+
* Holds if `e` is an access to a value that is guarded by `instanceof t`.
430434
*/
431-
predicate arrayInstanceOfGuarded(ArrayAccess aa, RefType t) {
432-
exists(InstanceOfExpr ioe, BaseSsaVariable v1, BaseSsaVariable v2, ArrayAccess aa1 |
433-
ioe.getExpr() = aa1 and
435+
private predicate instanceOfGuarded(Expr e, RefType t) {
436+
exists(InstanceOfExpr ioe |
434437
t = ioe.getCheckedType() and
435-
aa1.getArray() = v1.getAUse() and
436-
aa1.getIndexExpr() = v2.getAUse() and
437-
aa.getArray() = v1.getAUse() and
438-
aa.getIndexExpr() = v2.getAUse() and
439-
guardControls_v1(ioe, aa.getBasicBlock(), true)
438+
e = getAProbableAlias(ioe.getExpr()) and
439+
guardControls_v1(ioe, e.getBasicBlock(), true)
440440
)
441441
}
442442

443443
/**
444444
* Holds if `va` is an access to a value that is guarded by `case T t`.
445445
*/
446-
private predicate patternCaseGuarded(VarAccess va, RefType t) {
447-
exists(PatternCase pc, BaseSsaVariable v |
448-
va = v.getAUse() and
449-
(
450-
pc.getSwitch().getExpr() = v.getAUse() or
451-
pc.getSwitchExpr().getExpr() = v.getAUse()
452-
) and
453-
pc.getDecl().getBasicBlock().bbDominates(va.getBasicBlock()) and
454-
t = pc.getDecl().getType()
446+
private predicate patternCaseGuarded(Expr e, RefType t) {
447+
exists(PatternCase pc |
448+
e = getAProbableAlias([pc.getSwitch().getExpr(), pc.getSwitchExpr().getExpr()]) and
449+
guardControls_v1(pc, e.getBasicBlock(), true) and
450+
t = pc.getDecl().getType()
455451
)
456452
}
457453

@@ -478,7 +474,6 @@ private predicate typeFlowBaseCand(TypeFlowNode n, RefType t) {
478474
upcastEnhancedForStmt(n.asSsa(), srctype) or
479475
downcastSuccessor(n.asExpr(), srctype) or
480476
instanceOfGuarded(n.asExpr(), srctype) or
481-
arrayInstanceOfGuarded(n.asExpr(), srctype) or
482477
n.asExpr().(FunctionalExpr).getConstructedType() = srctype or
483478
superAccess(n.asExpr(), srctype) or
484479
patternCaseGuarded(n.asExpr(), srctype)

java/ql/test/library-tests/typeflow/A.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,14 @@ public void m8(Object[] xs, int i) {
9292
Object r = n;
9393
}
9494
}
95+
96+
public void m9(Object[] xs, int i) {
97+
switch (xs[i]) {
98+
case Integer i2 -> {
99+
Object n = xs[i];
100+
Object r = n;
101+
}
102+
default -> { }
103+
}
104+
}
95105
}

java/ql/test/library-tests/typeflow/typeflow.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@
1313
| A.java:67:22:67:22 | x | Integer | false |
1414
| A.java:70:23:70:24 | x2 | Integer | false |
1515
| A.java:92:18:92:18 | n | Integer | false |
16+
| A.java:100:20:100:20 | n | Integer | false |
1617
| UnionTypes.java:45:7:45:7 | x | Inter | false |
1718
| UnionTypes.java:48:23:48:23 | x | Inter | false |

0 commit comments

Comments
 (0)