mirror of
https://github.com/github/codeql.git
synced 2026-04-26 01:05:15 +02:00
Fix switchCaseControls and hasBranchEdge to account for mixed patterns and constant cases
This commit is contained in:
@@ -152,13 +152,16 @@ class Guard extends ExprParent {
|
||||
bb2 = cb.getTestSuccessor(branch)
|
||||
)
|
||||
or
|
||||
exists(SwitchCase sc, ControlFlowNode pred |
|
||||
exists(SwitchCase sc |
|
||||
sc = this and
|
||||
// Pattern cases are handled as ConditionBlocks above.
|
||||
not sc instanceof PatternCase and
|
||||
branch = true and
|
||||
bb2.getFirstNode() = sc.getControlFlowNode() and
|
||||
pred = sc.getControlFlowNode().getAPredecessor() and
|
||||
pred.(Expr).getParent*() = sc.getSelectorExpr() and
|
||||
bb1 = pred.getBasicBlock()
|
||||
bb1 = sc.getControlFlowNode().getAPredecessor().getBasicBlock() and
|
||||
// This is either the top of the switch block, or a preceding pattern case
|
||||
// if one exists.
|
||||
this.getBasicBlock() = bb1
|
||||
)
|
||||
or
|
||||
preconditionBranchEdge(this, bb1, bb2, branch)
|
||||
@@ -245,20 +248,20 @@ class TypeTestGuard extends Guard {
|
||||
}
|
||||
|
||||
private predicate switchCaseControls(SwitchCase sc, BasicBlock bb) {
|
||||
exists(BasicBlock caseblock, Expr selector |
|
||||
selector = sc.getSelectorExpr() and
|
||||
(
|
||||
if sc instanceof PatternCase
|
||||
then caseblock.getANode() = sc.(PatternCase).getPattern().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)
|
||||
exists(BasicBlock caseblock |
|
||||
caseblock.getFirstNode() = sc.getControlFlowNode() and
|
||||
caseblock.bbDominates(bb) and
|
||||
// Check we can't fall through from a previous block:
|
||||
forall(ControlFlowNode pred | pred = sc.getControlFlowNode().getAPredecessor() |
|
||||
// Branch straight from the switch selector:
|
||||
pred.(Expr).getParent*() = sc.getSelectorExpr()
|
||||
or
|
||||
// Branch from a predecessor pattern case (note pattern cases cannot ever fall through)
|
||||
pred = sc.getSiblingCase(_).(PatternCase)
|
||||
or
|
||||
// Branch from a predecessor pattern case's guard test, which also can't be a fallthrough edge
|
||||
pred.(Expr).getParent*() = sc.getSiblingCase(_).(PatternCase).getGuard()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -38,3 +38,19 @@ Test.java:
|
||||
# 12| 0: [StringLiteral] "d"
|
||||
# 13| 3: [DefaultCase] default
|
||||
# 13| -1: [BlockStmt] { ... }
|
||||
# 15| 2: [SwitchStmt] switch (...)
|
||||
# 15| -1: [VarAccess] s
|
||||
# 16| 0: [PatternCase] case T t ...
|
||||
# 16| -3: [EQExpr] ... == ...
|
||||
# 16| 0: [MethodCall] length(...)
|
||||
# 16| -1: [VarAccess] s
|
||||
# 16| 1: [IntegerLiteral] 4
|
||||
# 16| -1: [BlockStmt] { ... }
|
||||
#-----| 0: (Single Local Variable Declaration)
|
||||
# 16| 0: [TypeAccess] String
|
||||
# 16| 1: [LocalVariableDeclExpr] s2
|
||||
# 17| 1: [ConstCase] case ...
|
||||
# 17| -1: [BlockStmt] { ... }
|
||||
# 17| 0: [StringLiteral] "e"
|
||||
# 18| 2: [DefaultCase] default
|
||||
# 18| -1: [BlockStmt] { ... }
|
||||
|
||||
@@ -12,5 +12,10 @@ class Test {
|
||||
case "d" -> { }
|
||||
default -> { }
|
||||
}
|
||||
switch (s) {
|
||||
case String s2 when s.length() == 4 -> { }
|
||||
case "e" -> { }
|
||||
default -> { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,3 +6,5 @@
|
||||
| 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 ... |
|
||||
| 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 |
|
||||
| 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 ... |
|
||||
| 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 |
|
||||
| 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 ... |
|
||||
|
||||
@@ -1 +1 @@
|
||||
//semmle-extractor-options: --javac-args -source 14 -target 14
|
||||
//semmle-extractor-options: --javac-args --release 21
|
||||
|
||||
Reference in New Issue
Block a user