Skip to content

Commit a0c8491

Browse files
committed
Java: Add guards-logic qltest with inline expectation.
1 parent aa65f54 commit a0c8491

File tree

4 files changed

+230
-0
lines changed

4 files changed

+230
-0
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
public class Guards {
2+
static void chk() { }
3+
4+
static boolean g(Object lbl) { return lbl.hashCode() > 10; }
5+
6+
static void checkTrue(boolean b, String msg) {
7+
if (!b) throw new Error(msg);
8+
}
9+
10+
static void checkFalse(boolean b, String msg) {
11+
checkTrue(!b, msg);
12+
}
13+
14+
void t1(int[] a, String s) {
15+
if (g("A")) {
16+
chk(); // $ guarded=g(A):true
17+
} else {
18+
chk(); // $ guarded=g(A):false
19+
}
20+
21+
boolean b = g(1) ? g(2) : true;
22+
if (b != false) {
23+
chk(); // $ guarded=...?...:...:true guarded='b != false:true' guarded=b:true
24+
} else {
25+
chk(); // $ guarded=...?...:...:false guarded='b != false:false' guarded=b:false guarded=g(1):true guarded=g(2):false
26+
}
27+
int sz = a != null ? a.length : 0;
28+
for (int i = 0; i < sz; i++) {
29+
chk(); // $ guarded='a != null:true' guarded='i < sz:true'
30+
int e = a[i];
31+
if (e > 2) break;
32+
}
33+
chk(); // nothing guards here
34+
35+
if (g(3))
36+
s = "bar";
37+
switch (s) {
38+
case "bar":
39+
chk(); // $ guarded='s:match "bar"'
40+
break;
41+
case "foo":
42+
chk(); // $ guarded='s:match "foo"' guarded=g(3):false
43+
break;
44+
default:
45+
chk(); // $ guarded='s:non-match "bar"' guarded='s:non-match "foo"' guarded='s:match default' guarded=g(3):false
46+
break;
47+
}
48+
49+
Object o = g(4) ? null : s;
50+
if (o instanceof String) {
51+
chk(); // $ guarded=...instanceof...:true guarded=g(4):false
52+
}
53+
}
54+
55+
void t2() {
56+
checkTrue(g(1), "A");
57+
checkFalse(g(2), "B");
58+
chk(); // $ guarded=checkTrue(A):true guarded=g(1):true guarded=checkFalse(B):false guarded=g(2):false
59+
}
60+
61+
void t3() {
62+
boolean b = g(1) && (g(2) || g(3));
63+
if (b) {
64+
chk(); // $ guarded=b:true guarded='g(...) && ... \|\| ...:true' guarded=g(1):true guarded='g(...) \|\| g(...):true'
65+
} else {
66+
chk(); // $ guarded=b:false guarded='g(...) && ... \|\| ...:false'
67+
}
68+
b = g(4) || !g(5);
69+
if (b) {
70+
chk(); // $ guarded=b:true guarded='g(...) \|\| !...:true'
71+
} else {
72+
chk(); // $ guarded=b:false guarded='g(...) \|\| !...:false' guarded=g(4):false guarded=!...:false guarded=g(5):true
73+
}
74+
}
75+
76+
enum Val {
77+
E1,
78+
E2,
79+
E3
80+
}
81+
82+
void t4() {
83+
Val x = null; // unique value
84+
if (g(1)) x = Val.E1; // unique value
85+
if (g(2)) x = Val.E2;
86+
if (g("Alt2")) x = Val.E2;
87+
if (g(3)) x = Val.E3; // unique value
88+
if (x == null)
89+
chk(); // $ guarded='x == null:true' guarded=g(3):false
90+
switch (x) {
91+
case E1:
92+
chk(); // $ guarded='x:match E1' guarded=g(1):true guarded=g(3):false
93+
break;
94+
case E2:
95+
chk(); // $ guarded='x:match E2' guarded=g(3):false
96+
break;
97+
case E3:
98+
chk(); // $ guarded='x:match E3' guarded=g(3):true
99+
break;
100+
}
101+
Object o = g(4) ? new Object() : null;
102+
if (o == null) {
103+
chk(); // $ guarded='o == null:true' guarded=g(4):false
104+
} else {
105+
chk(); // $ guarded='o == null:false' guarded=g(4):true
106+
}
107+
}
108+
109+
void t5(String foo) {
110+
String base = foo;
111+
if (base == null) {
112+
base = "/user";
113+
}
114+
if (base.equals("/"))
115+
chk(); // $ guarded=equals(/):true guarded='base == null:false'
116+
}
117+
118+
void t6() {
119+
Object o = null;
120+
if (g(1)) {
121+
o = new Object();
122+
if (g(2)) { }
123+
}
124+
if (o != null) {
125+
chk(); // $ guarded='o != null:true'
126+
} else {
127+
chk(); // $ guarded='o != null:false' guarded=g(1):false
128+
}
129+
}
130+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
| Guards.java:16:7:16:11 | chk(...) | g(A):true |
2+
| Guards.java:18:7:18:11 | chk(...) | g(A):false |
3+
| Guards.java:23:7:23:11 | chk(...) | 'b != false:true' |
4+
| Guards.java:23:7:23:11 | chk(...) | ...?...:...:true |
5+
| Guards.java:23:7:23:11 | chk(...) | b:true |
6+
| Guards.java:25:7:25:11 | chk(...) | 'b != false:false' |
7+
| Guards.java:25:7:25:11 | chk(...) | ...?...:...:false |
8+
| Guards.java:25:7:25:11 | chk(...) | b:false |
9+
| Guards.java:25:7:25:11 | chk(...) | g(1):true |
10+
| Guards.java:25:7:25:11 | chk(...) | g(2):false |
11+
| Guards.java:29:7:29:11 | chk(...) | 'a != null:true' |
12+
| Guards.java:29:7:29:11 | chk(...) | 'i < sz:true' |
13+
| Guards.java:39:9:39:13 | chk(...) | 's:match "bar"' |
14+
| Guards.java:42:9:42:13 | chk(...) | 's:match "foo"' |
15+
| Guards.java:42:9:42:13 | chk(...) | g(3):false |
16+
| Guards.java:45:9:45:13 | chk(...) | 's:match default' |
17+
| Guards.java:45:9:45:13 | chk(...) | 's:non-match "bar"' |
18+
| Guards.java:45:9:45:13 | chk(...) | 's:non-match "foo"' |
19+
| Guards.java:45:9:45:13 | chk(...) | g(3):false |
20+
| Guards.java:51:7:51:11 | chk(...) | ...instanceof...:true |
21+
| Guards.java:51:7:51:11 | chk(...) | g(4):false |
22+
| Guards.java:58:5:58:9 | chk(...) | checkFalse(B):false |
23+
| Guards.java:58:5:58:9 | chk(...) | checkTrue(A):true |
24+
| Guards.java:58:5:58:9 | chk(...) | g(1):true |
25+
| Guards.java:58:5:58:9 | chk(...) | g(2):false |
26+
| Guards.java:64:7:64:11 | chk(...) | 'g(...) && ... \|\| ...:true' |
27+
| Guards.java:64:7:64:11 | chk(...) | 'g(...) \|\| g(...):true' |
28+
| Guards.java:64:7:64:11 | chk(...) | b:true |
29+
| Guards.java:64:7:64:11 | chk(...) | g(1):true |
30+
| Guards.java:66:7:66:11 | chk(...) | 'g(...) && ... \|\| ...:false' |
31+
| Guards.java:66:7:66:11 | chk(...) | b:false |
32+
| Guards.java:70:7:70:11 | chk(...) | 'g(...) \|\| !...:true' |
33+
| Guards.java:70:7:70:11 | chk(...) | b:true |
34+
| Guards.java:72:7:72:11 | chk(...) | !...:false |
35+
| Guards.java:72:7:72:11 | chk(...) | 'g(...) \|\| !...:false' |
36+
| Guards.java:72:7:72:11 | chk(...) | b:false |
37+
| Guards.java:72:7:72:11 | chk(...) | g(4):false |
38+
| Guards.java:72:7:72:11 | chk(...) | g(5):true |
39+
| Guards.java:89:7:89:11 | chk(...) | 'x == null:true' |
40+
| Guards.java:89:7:89:11 | chk(...) | g(3):false |
41+
| Guards.java:92:9:92:13 | chk(...) | 'x:match E1' |
42+
| Guards.java:92:9:92:13 | chk(...) | g(1):true |
43+
| Guards.java:92:9:92:13 | chk(...) | g(3):false |
44+
| Guards.java:95:9:95:13 | chk(...) | 'x:match E2' |
45+
| Guards.java:95:9:95:13 | chk(...) | g(3):false |
46+
| Guards.java:98:9:98:13 | chk(...) | 'x:match E3' |
47+
| Guards.java:98:9:98:13 | chk(...) | g(3):true |
48+
| Guards.java:103:7:103:11 | chk(...) | 'o == null:true' |
49+
| Guards.java:103:7:103:11 | chk(...) | g(4):false |
50+
| Guards.java:105:7:105:11 | chk(...) | 'o == null:false' |
51+
| Guards.java:105:7:105:11 | chk(...) | g(4):true |
52+
| Guards.java:115:7:115:11 | chk(...) | 'base == null:false' |
53+
| Guards.java:115:7:115:11 | chk(...) | equals(/):true |
54+
| Guards.java:125:7:125:11 | chk(...) | 'o != null:true' |
55+
| Guards.java:127:7:127:11 | chk(...) | 'o != null:false' |
56+
| Guards.java:127:7:127:11 | chk(...) | g(1):false |
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import java
2+
import semmle.code.java.controlflow.Guards
3+
import codeql.util.Boolean
4+
5+
string ppGuard(Guard g, Boolean branch) {
6+
exists(MethodCall mc, Literal s |
7+
mc = g and
8+
mc.getAnArgument() = s and
9+
result = mc.getMethod().getName() + "(" + s.getValue() + ")" + ":" + branch
10+
)
11+
or
12+
exists(BinaryExpr bin |
13+
bin = g and
14+
result = "'" + bin.getLeftOperand() + bin.getOp() + bin.getRightOperand() + ":" + branch + "'"
15+
)
16+
or
17+
exists(SwitchCase cc, Expr s, string match, string value |
18+
cc = g and
19+
cc.getSelectorExpr() = s and
20+
(
21+
cc.(ConstCase).getValue().toString() = value
22+
or
23+
cc instanceof DefaultCase and value = "default"
24+
) and
25+
if branch = true then match = ":match " else match = ":non-match "
26+
|
27+
result = "'" + s.toString() + match + value + "'"
28+
)
29+
}
30+
31+
query predicate guarded(MethodCall mc, string guard) {
32+
mc.getMethod().hasName("chk") and
33+
exists(Guard g, BasicBlock bb, boolean branch |
34+
g.controls(bb, branch) and
35+
mc.getBasicBlock() = bb
36+
|
37+
guard = ppGuard(g, branch)
38+
or
39+
not exists(ppGuard(g, branch)) and
40+
guard = g.toString() + ":" + branch
41+
)
42+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
query: GuardsInline.ql
2+
postprocess: utils/test/InlineExpectationsTestQuery.ql

0 commit comments

Comments
 (0)