Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion java/ql/src/semmle/code/java/Statement.qll
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,14 @@ class SwitchCase extends Stmt, @case {
*/
SwitchExpr getSwitchExpr() { result.getACase() = this }

/**
* Gets the expression of the surrounding switch that this case is compared
* against.
*/
Expr getSelectorExpr() {
result = this.getSwitch().getExpr() or result = this.getSwitchExpr().getExpr()
}

/**
* PREVIEW FEATURE in Java 12. Subject to removal in a future release.
*
Expand Down Expand Up @@ -625,7 +633,10 @@ class BreakStmt extends Stmt, @breakstmt {
override string pp() {
if this.hasLabel()
then result = "break " + this.getLabel()
else if this.hasValue() then result = "break ..." else result = "break"
else
if this.hasValue()
then result = "break ..."
else result = "break"
}

/** This statement's Halstead ID (used to compute Halstead metrics). */
Expand Down
16 changes: 9 additions & 7 deletions java/ql/src/semmle/code/java/controlflow/Guards.qll
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ class Guard extends ExprParent {
/** Gets the statement containing this guard. */
Stmt getEnclosingStmt() {
result = this.(Expr).getEnclosingStmt() or
result = this.(SwitchCase).getSwitch()
result = this.(SwitchCase).getSwitch() or
result = this.(SwitchCase).getSwitchExpr().getEnclosingStmt()
}

/**
Expand Down Expand Up @@ -126,7 +127,7 @@ class Guard extends ExprParent {
branch = true and
bb2.getFirstNode() = sc.getControlFlowNode() and
pred = sc.getControlFlowNode().getAPredecessor() and
pred.(Expr).getParent*() = sc.getSwitch().getExpr() and
pred.(Expr).getParent*() = sc.getSelectorExpr() and
bb1 = pred.getBasicBlock()
)
or
Expand Down Expand Up @@ -160,12 +161,12 @@ class Guard extends ExprParent {
}

private predicate switchCaseControls(SwitchCase sc, BasicBlock bb) {
exists(BasicBlock caseblock, SwitchStmt ss |
ss.getACase() = sc and
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*() = ss.getExpr()
pred.(Expr).getParent*() = selector
)
)
}
Expand Down Expand Up @@ -254,7 +255,8 @@ private predicate equalityGuard(Guard g, Expr e1, Expr e2, boolean polarity) {
exists(ConstCase cc |
cc = g and
polarity = true and
cc.getSwitch().getExpr().getProperExpr() = e1 and
cc.getValue() = e2
cc.getSelectorExpr().getProperExpr() = e1 and
cc.getValue() = e2 and
strictcount(cc.getValue(_)) = 1
)
}
9 changes: 9 additions & 0 deletions java/ql/test/library-tests/guards12/Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Test {
void foo(String s) {
int x = switch(s) {
case "a", "b" -> 1;
case "c" -> 2;
default -> 3;
};
}
}
1 change: 1 addition & 0 deletions java/ql/test/library-tests/guards12/guard.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
| Test.java:5:7:5:17 | stmt | Test.java:3:20:3:20 | s | Test.java:5:12:5:14 | "c" | true | true | Test.java:5:7:5:17 | stmt |
8 changes: 8 additions & 0 deletions java/ql/test/library-tests/guards12/guard.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import java
import semmle.code.java.controlflow.Guards

from Guard g, BasicBlock bb, boolean branch, VarAccess e1, Expr e2, boolean pol
where
g.controls(bb, branch) and
g.isEquality(e1, e2, pol)
select g, e1, e2, pol, branch, bb
1 change: 1 addition & 0 deletions java/ql/test/library-tests/guards12/options
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args --enable-preview -source 12 -target 12