Skip to content

Commit 2600906

Browse files
committed
Java: Fix regression.
1 parent 1a66f7e commit 2600906

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

java/ql/src/semmle/code/java/dataflow/RangeAnalysis.qll

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,21 +133,41 @@ private predicate boundCondition(ComparisonExpr comp, SsaVariable v, Expr e, int
133133
)
134134
}
135135

136+
private predicate gcdInput(int x, int y) {
137+
exists(ComparisonExpr comp, Bound b |
138+
exprModulus(comp.getLesserOperand(), b, _, x) and
139+
exprModulus(comp.getGreaterOperand(), b, _, y)
140+
) or
141+
exists(int x0, int y0 |
142+
gcdInput(x0, y0) and
143+
x = y0 and
144+
y = x0 % y0
145+
)
146+
}
147+
148+
private int gcd(int x, int y) {
149+
result = x.abs() and y = 0 and gcdInput(x, y)
150+
or
151+
result = gcd(y, x % y) and y != 0 and gcdInput(x, y)
152+
}
153+
136154
/**
137155
* Holds if `comp` is a comparison between `x` and `y` for which `y - x` has a
138156
* fixed value modulo some `mod > 1`, such that the comparison can be
139157
* strengthened by `strengthen` when evaluating to `testIsTrue`.
140158
*/
141159
private predicate modulusComparison(ComparisonExpr comp, boolean testIsTrue, int strengthen) {
142-
exists(Bound b, int v1, int v2, int mod, boolean resultIsStrict, int d, int k |
160+
exists(Bound b, int v1, int v2, int mod1, int mod2, int mod, boolean resultIsStrict, int d, int k |
143161
// If `x <= y` and `x =(mod) b + v1` and `y =(mod) b + v2` then
144162
// `0 <= y - x =(mod) v2 - v1`. By choosing `k =(mod) v2 - v1` with
145163
// `0 <= k < mod` we get `k <= y - x`. If the resulting comparison is
146164
// strict then the strengthening amount is instead `k - 1` modulo `mod`:
147165
// `x < y` means `0 <= y - x - 1 =(mod) k - 1` so `k - 1 <= y - x - 1` and
148166
// thus `k - 1 < y - x` with `0 <= k - 1 < mod`.
149-
exprModulus(comp.getLesserOperand(), b, v1, mod) and
150-
exprModulus(comp.getGreaterOperand(), b, v2, mod) and
167+
exprModulus(comp.getLesserOperand(), b, v1, mod1) and
168+
exprModulus(comp.getGreaterOperand(), b, v2, mod2) and
169+
mod = gcd(mod1, mod2) and
170+
mod != 1 and
151171
(testIsTrue = true or testIsTrue = false) and
152172
(if comp.isStrict() then resultIsStrict = testIsTrue else resultIsStrict = testIsTrue.booleanNot()) and
153173
(resultIsStrict = true and d = 1 or resultIsStrict = false and d = 0) and

java/ql/test/query-tests/RangeAnalysis/A.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,15 @@ void m11(int n) {
151151
}
152152
}
153153

154+
void m12() {
155+
int[] a = new int[] { 1, 2, 3, 4, 5, 6 };
156+
int sum = 0;
157+
for (int i = 0; i < a.length; i += 2) {
158+
sum += a[i] + a[i + 1]; // OK
159+
}
160+
int[] b = new int[8];
161+
for (int i = 2; i < 8; i += 2) {
162+
sum += b[i] + b[i + 1]; // OK
163+
}
164+
}
154165
}

0 commit comments

Comments
 (0)