Skip to content

Commit c2de08c

Browse files
authored
Merge pull request github#3499 from aschackmull/java/instanceof-pattern-cfg
Java: Add CFG edges for Java 14 pattern-matching instanceof.
2 parents 732da9c + 796eac1 commit c2de08c

File tree

7 files changed

+93
-3
lines changed

7 files changed

+93
-3
lines changed

java/ql/src/semmle/code/java/ControlFlowGraph.qll

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ private module ControlFlowGraphImpl {
405405
* Expressions and statements with CFG edges in post-order AST traversal.
406406
*
407407
* This includes most expressions, except those that initiate or propagate branching control
408-
* flow (`LogicExpr`, `ConditionalExpr`), and parentheses, which aren't in the CFG.
408+
* flow (`LogicExpr`, `ConditionalExpr`).
409409
* Only a few statements are included; those with specific side-effects
410410
* occurring after the evaluation of their children, that is, `Call`, `ReturnStmt`,
411411
* and `ThrowStmt`. CFG nodes without child nodes in the CFG that may complete
@@ -429,9 +429,10 @@ private module ControlFlowGraphImpl {
429429
or
430430
this instanceof CastExpr
431431
or
432-
this instanceof InstanceOfExpr
432+
this instanceof InstanceOfExpr and not this.(InstanceOfExpr).isPattern()
433433
or
434-
this instanceof LocalVariableDeclExpr
434+
this instanceof LocalVariableDeclExpr and
435+
not this = any(InstanceOfExpr ioe).getLocalVariableDeclExpr()
435436
or
436437
this instanceof RValue
437438
or
@@ -573,6 +574,8 @@ private module ControlFlowGraphImpl {
573574
or
574575
result = first(n.(PostOrderNode).firstChild())
575576
or
577+
result = first(n.(InstanceOfExpr).getExpr())
578+
or
576579
result = first(n.(SynchronizedStmt).getExpr())
577580
or
578581
result = n and
@@ -707,6 +710,12 @@ private module ControlFlowGraphImpl {
707710
last(condexpr.getTrueExpr(), last, completion)
708711
)
709712
or
713+
exists(InstanceOfExpr ioe | ioe.isPattern() and ioe = n |
714+
last = n and completion = basicBooleanCompletion(false)
715+
or
716+
last = ioe.getLocalVariableDeclExpr() and completion = basicBooleanCompletion(true)
717+
)
718+
or
710719
// The last node of a node executed in post-order is the node itself.
711720
n.(PostOrderNode).mayCompleteNormally() and last = n and completion = NormalCompletion()
712721
or
@@ -916,6 +925,14 @@ private module ControlFlowGraphImpl {
916925
result = first(e.getFalseExpr())
917926
)
918927
or
928+
exists(InstanceOfExpr ioe | ioe.isPattern() |
929+
last(ioe.getExpr(), n, completion) and completion = NormalCompletion() and result = ioe
930+
or
931+
n = ioe and
932+
result = ioe.getLocalVariableDeclExpr() and
933+
completion = basicBooleanCompletion(true)
934+
)
935+
or
919936
// In other expressions control flows from left to right and ends in the node itself.
920937
exists(PostOrderNode p, int i |
921938
last(p.getChildNode(i), n, completion) and completion = NormalCompletion()
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
class TestInstanceOfPattern {
2+
private String s = "field";
3+
void test(Object obj) {
4+
if (obj instanceof String s) {
5+
if (s.contains("abc")) {}
6+
} else {
7+
if (s.contains("def")) {}
8+
}
9+
}
10+
void test2(Object obj) {
11+
if (!(obj instanceof String s)) {
12+
if (s.contains("abc")) {}
13+
} else {
14+
if (s.contains("def")) {}
15+
}
16+
}
17+
void test3(Object obj) {
18+
if (obj instanceof String s && s.length() > 5) {
19+
if (s.contains("abc")) {}
20+
} else {
21+
if (s.contains("def")) {}
22+
}
23+
}
24+
void test4(Object obj) {
25+
if (obj instanceof String s || s.length() > 5) {
26+
if (s.contains("abc")) {}
27+
} else {
28+
if (s.contains("def")) {}
29+
}
30+
}
31+
}

java/ql/test/library-tests/ssa/adjacentUses.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,6 @@
3030
| Test.java:20:14:20:14 | y | Test.java:31:14:31:14 | y |
3131
| Test.java:27:19:27:19 | i | Test.java:28:9:28:9 | i |
3232
| Test.java:28:9:28:9 | i | Test.java:27:25:27:25 | i |
33+
| TestInstanceOfPattern.java:18:34:18:34 | s | TestInstanceOfPattern.java:19:8:19:8 | s |
34+
| TestInstanceOfPattern.java:25:34:25:34 | s | TestInstanceOfPattern.java:26:8:26:8 | s |
35+
| TestInstanceOfPattern.java:25:34:25:34 | s | TestInstanceOfPattern.java:28:8:28:8 | s |

java/ql/test/library-tests/ssa/firstUse.expected

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,15 @@
5858
| Test.java:27:25:27:27 | SSA def(i) | Test.java:27:19:27:19 | i |
5959
| Test.java:28:4:28:9 | SSA def(x) | Test.java:28:4:28:4 | x |
6060
| Test.java:28:4:28:9 | SSA def(x) | Test.java:31:10:31:10 | x |
61+
| TestInstanceOfPattern.java:3:24:9:2 | SSA init(obj) | TestInstanceOfPattern.java:4:7:4:9 | obj |
62+
| TestInstanceOfPattern.java:4:29:4:29 | SSA def(s) | TestInstanceOfPattern.java:5:8:5:8 | s |
63+
| TestInstanceOfPattern.java:7:8:7:8 | SSA impl upd[untracked](this.s) | TestInstanceOfPattern.java:7:8:7:8 | s |
64+
| TestInstanceOfPattern.java:10:25:16:2 | SSA init(obj) | TestInstanceOfPattern.java:11:9:11:11 | obj |
65+
| TestInstanceOfPattern.java:11:31:11:31 | SSA def(s) | TestInstanceOfPattern.java:14:8:14:8 | s |
66+
| TestInstanceOfPattern.java:12:8:12:8 | SSA impl upd[untracked](this.s) | TestInstanceOfPattern.java:12:8:12:8 | s |
67+
| TestInstanceOfPattern.java:17:25:23:2 | SSA init(obj) | TestInstanceOfPattern.java:18:7:18:9 | obj |
68+
| TestInstanceOfPattern.java:18:29:18:29 | SSA def(s) | TestInstanceOfPattern.java:18:34:18:34 | s |
69+
| TestInstanceOfPattern.java:21:8:21:8 | SSA impl upd[untracked](this.s) | TestInstanceOfPattern.java:21:8:21:8 | s |
70+
| TestInstanceOfPattern.java:24:25:30:2 | SSA init(obj) | TestInstanceOfPattern.java:25:7:25:9 | obj |
71+
| TestInstanceOfPattern.java:24:25:30:2 | SSA init(this.s) | TestInstanceOfPattern.java:25:34:25:34 | s |
72+
| TestInstanceOfPattern.java:24:25:30:2 | SSA init(this.s) | TestInstanceOfPattern.java:26:8:26:8 | s |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
//semmle-extractor-options: --javac-args --enable-preview -source 14 -target 14

java/ql/test/library-tests/ssa/ssaDef.expected

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,15 @@
9191
| Test.java:27:8:27:16 | i | Test.java:27:12:27:16 | i | SSA def(i) |
9292
| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) |
9393
| Test.java:27:8:27:16 | i | Test.java:27:25:27:27 | ...++ | SSA def(i) |
94+
| TestInstanceOfPattern.java:3:12:3:21 | obj | TestInstanceOfPattern.java:3:24:9:2 | stmt | SSA init(obj) |
95+
| TestInstanceOfPattern.java:4:22:4:29 | s | TestInstanceOfPattern.java:4:29:4:29 | s | SSA def(s) |
96+
| TestInstanceOfPattern.java:7:8:7:8 | this.s | TestInstanceOfPattern.java:7:8:7:8 | s | SSA impl upd[untracked](this.s) |
97+
| TestInstanceOfPattern.java:10:13:10:22 | obj | TestInstanceOfPattern.java:10:25:16:2 | stmt | SSA init(obj) |
98+
| TestInstanceOfPattern.java:11:24:11:31 | s | TestInstanceOfPattern.java:11:31:11:31 | s | SSA def(s) |
99+
| TestInstanceOfPattern.java:12:8:12:8 | this.s | TestInstanceOfPattern.java:12:8:12:8 | s | SSA impl upd[untracked](this.s) |
100+
| TestInstanceOfPattern.java:17:13:17:22 | obj | TestInstanceOfPattern.java:17:25:23:2 | stmt | SSA init(obj) |
101+
| TestInstanceOfPattern.java:18:22:18:29 | s | TestInstanceOfPattern.java:18:29:18:29 | s | SSA def(s) |
102+
| TestInstanceOfPattern.java:21:8:21:8 | this.s | TestInstanceOfPattern.java:21:8:21:8 | s | SSA impl upd[untracked](this.s) |
103+
| TestInstanceOfPattern.java:24:13:24:22 | obj | TestInstanceOfPattern.java:24:25:30:2 | stmt | SSA init(obj) |
104+
| TestInstanceOfPattern.java:25:22:25:29 | s | TestInstanceOfPattern.java:25:29:25:29 | s | SSA def(s) |
105+
| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | stmt | SSA init(this.s) |

java/ql/test/library-tests/ssa/ssaUse.expected

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,17 @@
5858
| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | Test.java:27:19:27:19 | i |
5959
| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | Test.java:27:25:27:25 | i |
6060
| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | Test.java:28:9:28:9 | i |
61+
| TestInstanceOfPattern.java:3:12:3:21 | obj | TestInstanceOfPattern.java:3:24:9:2 | stmt | SSA init(obj) | TestInstanceOfPattern.java:4:7:4:9 | obj |
62+
| TestInstanceOfPattern.java:4:22:4:29 | s | TestInstanceOfPattern.java:4:29:4:29 | s | SSA def(s) | TestInstanceOfPattern.java:5:8:5:8 | s |
63+
| TestInstanceOfPattern.java:7:8:7:8 | this.s | TestInstanceOfPattern.java:7:8:7:8 | s | SSA impl upd[untracked](this.s) | TestInstanceOfPattern.java:7:8:7:8 | s |
64+
| TestInstanceOfPattern.java:10:13:10:22 | obj | TestInstanceOfPattern.java:10:25:16:2 | stmt | SSA init(obj) | TestInstanceOfPattern.java:11:9:11:11 | obj |
65+
| TestInstanceOfPattern.java:11:24:11:31 | s | TestInstanceOfPattern.java:11:31:11:31 | s | SSA def(s) | TestInstanceOfPattern.java:14:8:14:8 | s |
66+
| TestInstanceOfPattern.java:12:8:12:8 | this.s | TestInstanceOfPattern.java:12:8:12:8 | s | SSA impl upd[untracked](this.s) | TestInstanceOfPattern.java:12:8:12:8 | s |
67+
| TestInstanceOfPattern.java:17:13:17:22 | obj | TestInstanceOfPattern.java:17:25:23:2 | stmt | SSA init(obj) | TestInstanceOfPattern.java:18:7:18:9 | obj |
68+
| TestInstanceOfPattern.java:18:22:18:29 | s | TestInstanceOfPattern.java:18:29:18:29 | s | SSA def(s) | TestInstanceOfPattern.java:18:34:18:34 | s |
69+
| TestInstanceOfPattern.java:18:22:18:29 | s | TestInstanceOfPattern.java:18:29:18:29 | s | SSA def(s) | TestInstanceOfPattern.java:19:8:19:8 | s |
70+
| TestInstanceOfPattern.java:21:8:21:8 | this.s | TestInstanceOfPattern.java:21:8:21:8 | s | SSA impl upd[untracked](this.s) | TestInstanceOfPattern.java:21:8:21:8 | s |
71+
| TestInstanceOfPattern.java:24:13:24:22 | obj | TestInstanceOfPattern.java:24:25:30:2 | stmt | SSA init(obj) | TestInstanceOfPattern.java:25:7:25:9 | obj |
72+
| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | stmt | SSA init(this.s) | TestInstanceOfPattern.java:25:34:25:34 | s |
73+
| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | stmt | SSA init(this.s) | TestInstanceOfPattern.java:26:8:26:8 | s |
74+
| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | stmt | SSA init(this.s) | TestInstanceOfPattern.java:28:8:28:8 | s |

0 commit comments

Comments
 (0)