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

Skip to content

Commit 668f445

Browse files
committed
Fix switchCaseControls and hasBranchEdge to account for mixed patterns and constant cases
1 parent c181440 commit 668f445

5 files changed

Lines changed: 45 additions & 19 deletions

File tree

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

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,16 @@ class Guard extends ExprParent {
152152
bb2 = cb.getTestSuccessor(branch)
153153
)
154154
or
155-
exists(SwitchCase sc, ControlFlowNode pred |
155+
exists(SwitchCase sc |
156156
sc = this and
157+
// Pattern cases are handled as ConditionBlocks above.
158+
not sc instanceof PatternCase and
157159
branch = true and
158160
bb2.getFirstNode() = sc.getControlFlowNode() and
159-
pred = sc.getControlFlowNode().getAPredecessor() and
160-
pred.(Expr).getParent*() = sc.getSelectorExpr() and
161-
bb1 = pred.getBasicBlock()
161+
bb1 = sc.getControlFlowNode().getAPredecessor().getBasicBlock() and
162+
// This is either the top of the switch block, or a preceding pattern case
163+
// if one exists.
164+
this.getBasicBlock() = bb1
162165
)
163166
or
164167
preconditionBranchEdge(this, bb1, bb2, branch)
@@ -245,20 +248,20 @@ class TypeTestGuard extends Guard {
245248
}
246249

247250
private predicate switchCaseControls(SwitchCase sc, BasicBlock bb) {
248-
exists(BasicBlock caseblock, Expr selector |
249-
selector = sc.getSelectorExpr() and
250-
(
251-
if sc instanceof PatternCase
252-
then caseblock.getANode() = sc.(PatternCase).getPattern().getControlFlowNode()
253-
else (
254-
caseblock.getFirstNode() = sc.getControlFlowNode() and
255-
// Check there is no fall-through edge from a previous case:
256-
forall(ControlFlowNode pred | pred = sc.getControlFlowNode().getAPredecessor() |
257-
pred.(Expr).getParent*() = selector
258-
)
259-
)
260-
) and
261-
caseblock.bbDominates(bb)
251+
exists(BasicBlock caseblock |
252+
caseblock.getFirstNode() = sc.getControlFlowNode() and
253+
caseblock.bbDominates(bb) and
254+
// Check we can't fall through from a previous block:
255+
forall(ControlFlowNode pred | pred = sc.getControlFlowNode().getAPredecessor() |
256+
// Branch straight from the switch selector:
257+
pred.(Expr).getParent*() = sc.getSelectorExpr()
258+
or
259+
// Branch from a predecessor pattern case (note pattern cases cannot ever fall through)
260+
pred = sc.getSiblingCase(_).(PatternCase)
261+
or
262+
// Branch from a predecessor pattern case's guard test, which also can't be a fallthrough edge
263+
pred.(Expr).getParent*() = sc.getSiblingCase(_).(PatternCase).getGuard()
264+
)
262265
)
263266
}
264267

java/ql/test/library-tests/guards12/PrintAst.expected

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,19 @@ Test.java:
3838
# 12| 0: [StringLiteral] "d"
3939
# 13| 3: [DefaultCase] default
4040
# 13| -1: [BlockStmt] { ... }
41+
# 15| 2: [SwitchStmt] switch (...)
42+
# 15| -1: [VarAccess] s
43+
# 16| 0: [PatternCase] case T t ...
44+
# 16| -3: [EQExpr] ... == ...
45+
# 16| 0: [MethodCall] length(...)
46+
# 16| -1: [VarAccess] s
47+
# 16| 1: [IntegerLiteral] 4
48+
# 16| -1: [BlockStmt] { ... }
49+
#-----| 0: (Single Local Variable Declaration)
50+
# 16| 0: [TypeAccess] String
51+
# 16| 1: [LocalVariableDeclExpr] s2
52+
# 17| 1: [ConstCase] case ...
53+
# 17| -1: [BlockStmt] { ... }
54+
# 17| 0: [StringLiteral] "e"
55+
# 18| 2: [DefaultCase] default
56+
# 18| -1: [BlockStmt] { ... }

java/ql/test/library-tests/guards12/Test.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,10 @@ void foo(String s) {
1212
case "d" -> { }
1313
default -> { }
1414
}
15+
switch (s) {
16+
case String s2 when s.length() == 4 -> { }
17+
case "e" -> { }
18+
default -> { }
19+
}
1520
}
1621
}

java/ql/test/library-tests/guards12/guard.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@
66
| Test.java:11:7:11:17 | case ... | Test.java:9:13:9:13 | s | Test.java:11:12:11:14 | "c" | true | true | Test.java:11:7:11:17 | case ... |
77
| Test.java:12:7:12:17 | case ... | Test.java:9:13:9:13 | s | Test.java:12:12:12:14 | "d" | true | false | Test.java:13:7:13:16 | default |
88
| Test.java:12:7:12:17 | case ... | Test.java:9:13:9:13 | s | Test.java:12:12:12:14 | "d" | true | true | Test.java:12:7:12:17 | case ... |
9+
| Test.java:17:7:17:17 | case ... | Test.java:15:13:15:13 | s | Test.java:17:12:17:14 | "e" | true | false | Test.java:18:7:18:16 | default |
10+
| Test.java:17:7:17:17 | case ... | Test.java:15:13:15:13 | s | Test.java:17:12:17:14 | "e" | true | true | Test.java:17:7:17:17 | case ... |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
//semmle-extractor-options: --javac-args -source 14 -target 14
1+
//semmle-extractor-options: --javac-args --release 21

0 commit comments

Comments
 (0)