Skip to content

Commit 25664d0

Browse files
committed
Java: Add support for non-integer bounds in inline expectations
1 parent 37935ee commit 25664d0

File tree

2 files changed

+76
-11
lines changed
  • java/ql/test/library-tests/dataflow/range-analysis-inline

2 files changed

+76
-11
lines changed

java/ql/test/library-tests/dataflow/range-analysis-inline/B.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
public class B {
2+
3+
// Use this method to mark non-integer bounds
4+
// that should also be annotated.
5+
static void bound(int b) { }
6+
27
public int forloop() {
38
int result = 0;
49
for (int i = 0;
@@ -91,4 +96,25 @@ public int oddwhileloop() {
9196
}
9297
return result; // $ bound="result = 5"
9398
}
99+
100+
static void arraylength(int[] arr) {
101+
bound(arr.length);
102+
for (int i = 0;
103+
i < arr.length;
104+
i++) { // $ bound="i <= arr.length - 1"
105+
arr[i]++; // $ bound="i <= arr.length - 1"
106+
}
107+
}
108+
109+
static int varbound(int b) {
110+
bound(b);
111+
int result = 0;
112+
for (int i = 0;
113+
i < b;
114+
i++) { // $ bound="i <= b - 1"
115+
result = i; // $ bound="i <= b - 1"
116+
}
117+
return result; // $ MISSING: bound="result <= b - 1"
118+
}
119+
94120
}

java/ql/test/library-tests/dataflow/range-analysis-inline/range.ql

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,69 @@
66
import java
77
import semmle.code.java.dataflow.RangeAnalysis
88
private import TestUtilities.InlineExpectationsTest as IET
9+
private import semmle.code.java.dataflow.DataFlow
910

1011
module RangeTest implements IET::TestSig {
1112
string getARelevantTag() { result = "bound" }
1213

1314
predicate hasActualResult(Location location, string element, string tag, string value) {
1415
tag = "bound" and
15-
exists(Expr e, int lower, int upper |
16-
constrained(e, lower, upper) and
17-
e instanceof VarRead and
18-
e.getCompilationUnit().fromSource()
19-
|
20-
location = e.getLocation() and
21-
element = e.toString() and
22-
if lower = upper
23-
then value = "\"" + e.toString() + " = " + lower.toString() + "\""
24-
else
25-
value = "\"" + e.toString() + " in [" + lower.toString() + ".." + upper.toString() + "]\""
16+
(
17+
// simple integer bounds (`ZeroBound`s)
18+
exists(Expr e, int lower, int upper |
19+
constrained(e, lower, upper) and
20+
e instanceof VarRead and
21+
e.getCompilationUnit().fromSource()
22+
|
23+
location = e.getLocation() and
24+
element = e.toString() and
25+
if lower = upper
26+
then value = "\"" + e.toString() + " = " + lower.toString() + "\""
27+
else
28+
value = "\"" + e.toString() + " in [" + lower.toString() + ".." + upper.toString() + "]\""
29+
)
30+
or
31+
// advanced bounds
32+
exists(
33+
Expr e, int delta, string deltaStr, boolean upper, string cmp, Bound b, Expr boundExpr
34+
|
35+
annotatedBound(e, b, boundExpr, delta, upper) and
36+
e instanceof VarRead and
37+
e.getCompilationUnit().fromSource() and
38+
(
39+
if delta = 0
40+
then deltaStr = ""
41+
else
42+
if delta > 0
43+
then deltaStr = " + " + delta.toString()
44+
else deltaStr = " - " + delta.abs().toString()
45+
) and
46+
if upper = true then cmp = "<=" else cmp = ">="
47+
|
48+
location = e.getLocation() and
49+
element = e.toString() and
50+
value = "\"" + e.toString() + " " + cmp + " " + boundExpr.toString() + deltaStr + "\""
51+
)
2652
)
2753
}
2854

2955
private predicate constrained(Expr e, int lower, int upper) {
3056
bounded(e, any(ZeroBound z), lower, false, _) and
3157
bounded(e, any(ZeroBound z), upper, true, _)
3258
}
59+
60+
private predicate annotatedBound(Expr e, Bound b, Expr boundExpr, int delta, boolean upper) {
61+
bounded(e, b, delta, upper, _) and
62+
// the expression for the bound is explicitly requested as being annotated
63+
// via a call such as
64+
// ```java
65+
// bound(expr);
66+
// ```
67+
boundExpr = b.getExpr() and
68+
exists(Call c | c.getCallee().getName() = "bound" and c.getArgument(0) = boundExpr) and
69+
// non-trivial bound
70+
(DataFlow::localFlow(DataFlow::exprNode(boundExpr), DataFlow::exprNode(e)) implies delta != 0)
71+
}
3372
}
3473

3574
import IET::MakeTest<RangeTest>

0 commit comments

Comments
 (0)