Skip to content

Commit 6b9aed2

Browse files
committed
Nullness library: recognise switches with null checks
1 parent 79b77ae commit 6b9aed2

File tree

6 files changed

+36
-3
lines changed

6 files changed

+36
-3
lines changed

java/ql/lib/semmle/code/java/Expr.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,6 +1542,11 @@ class SwitchExpr extends Expr, StmtParent, @switchexpr {
15421542
exists(YieldStmt yield | yield.getTarget() = this and result = yield.getValue())
15431543
}
15441544

1545+
/** Holds if this switch has a case handling a null literal. */
1546+
predicate hasNullCase() {
1547+
this.getAConstCase().getValue(_) instanceof NullLiteral
1548+
}
1549+
15451550
/** Gets a printable representation of this expression. */
15461551
override string toString() { result = "switch (...)" }
15471552

java/ql/lib/semmle/code/java/Statement.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,11 @@ class SwitchStmt extends Stmt, @switchstmt {
409409
/** Gets the expression of this `switch` statement. */
410410
Expr getExpr() { result.getParent() = this }
411411

412+
/** Holds if this switch has a case handling a null literal. */
413+
predicate hasNullCase() {
414+
this.getAConstCase().getValue(_) instanceof NullLiteral
415+
}
416+
412417
override string pp() { result = "switch (...)" }
413418

414419
override string toString() { result = "switch (...)" }

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ predicate dereference(Expr e) {
100100
or
101101
exists(SynchronizedStmt synch | synch.getExpr() = e)
102102
or
103-
exists(SwitchStmt switch | switch.getExpr() = e)
103+
exists(SwitchStmt switch | switch.getExpr() = e and not switch.hasNullCase())
104104
or
105-
exists(SwitchExpr switch | switch.getExpr() = e)
105+
exists(SwitchExpr switch | switch.getExpr() = e and not switch.hasNullCase())
106106
or
107107
exists(FieldAccess fa, Field f | fa.getQualifier() = e and fa.getField() = f and not f.isStatic())
108108
or
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
public class G {
2+
3+
public static void test(String s) {
4+
5+
if (s == null) {
6+
System.out.println("Is null");
7+
}
8+
9+
switch(s) { // OK; null case means this doesn't throw.
10+
case null -> System.out.println("Null");
11+
case "foo" -> System.out.println("Foo");
12+
default -> System.out.println("Something else");
13+
}
14+
15+
switch(s) { // BAD; lack of a null case means this may throw.
16+
case "foo" -> System.out.println("Foo");
17+
default -> System.out.println("Something else");
18+
}
19+
20+
}
21+
22+
}

java/ql/test/query-tests/Nullness/NullMaybe.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@
3535
| C.java:233:7:233:8 | xs | Variable $@ may be null at this access because of $@ assignment. | C.java:231:5:231:56 | int[] xs | xs | C.java:231:11:231:55 | xs | this |
3636
| F.java:11:5:11:7 | obj | Variable $@ may be null at this access as suggested by $@ null guard. | F.java:8:18:8:27 | obj | obj | F.java:9:9:9:19 | ... == ... | this |
3737
| F.java:17:5:17:7 | obj | Variable $@ may be null at this access as suggested by $@ null guard. | F.java:14:18:14:27 | obj | obj | F.java:15:9:15:19 | ... == ... | this |
38+
| G.java:15:12:15:12 | s | Variable $@ may be null at this access as suggested by $@ null guard. | G.java:3:27:3:34 | s | s | G.java:5:9:5:17 | ... == ... | this |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
//semmle-extractor-options: --javac-args -cp ${testdir}/../../stubs/junit-4.11:${testdir}/../../stubs/hamcrest-2.2:${testdir}/../../stubs/junit-jupiter-api-5.2.0
1+
//semmle-extractor-options: --javac-args --release 21 -cp ${testdir}/../../stubs/junit-4.11:${testdir}/../../stubs/hamcrest-2.2:${testdir}/../../stubs/junit-jupiter-api-5.2.0

0 commit comments

Comments
 (0)