Skip to content

Commit e7b0d39

Browse files
committed
Java: Refactor parts of RangeAnalysis needed for ModulusAnalysis.
1 parent a78a0b5 commit e7b0d39

File tree

2 files changed

+77
-44
lines changed

2 files changed

+77
-44
lines changed

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

Lines changed: 5 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -100,23 +100,6 @@ cached private module RangeAnalysisCache {
100100
private import RangeAnalysisCache
101101
import RangeAnalysisPublic
102102

103-
/**
104-
* Gets a condition that tests whether `v` equals `e + delta`.
105-
*
106-
* If the condition evaluates to `testIsTrue`:
107-
* - `isEq = true` : `v == e + delta`
108-
* - `isEq = false` : `v != e + delta`
109-
*/
110-
private Guard eqFlowCond(SsaVariable v, Expr e, int delta, boolean isEq, boolean testIsTrue) {
111-
exists(boolean eqpolarity |
112-
result.isEquality(ssaRead(v, delta), e, eqpolarity) and
113-
(testIsTrue = true or testIsTrue = false) and
114-
eqpolarity.booleanXor(testIsTrue).booleanNot() = isEq
115-
)
116-
or
117-
exists(boolean testIsTrue0 | implies_v2(result, testIsTrue, eqFlowCond(v, e, delta, isEq, testIsTrue0), testIsTrue0))
118-
}
119-
120103
/**
121104
* Holds if `comp` corresponds to:
122105
* - `upper = true` : `v <= e + delta` or `v < e + delta`
@@ -207,14 +190,8 @@ class CondReason extends Reason, TCondReason {
207190
* - `upper = false` : `v >= e + delta`
208191
*/
209192
private predicate boundFlowStepSsa(SsaVariable v, SsaReadPosition pos, Expr e, int delta, boolean upper, Reason reason) {
210-
exists(SsaExplicitUpdate upd | v = upd and pos.hasReadOfVar(v) and reason = TNoReason() |
211-
upd.getDefiningExpr().(VariableAssign).getSource() = e and delta = 0 and (upper = true or upper = false) or
212-
upd.getDefiningExpr().(PostIncExpr).getExpr() = e and delta = 1 and (upper = true or upper = false) or
213-
upd.getDefiningExpr().(PreIncExpr).getExpr() = e and delta = 1 and (upper = true or upper = false) or
214-
upd.getDefiningExpr().(PostDecExpr).getExpr() = e and delta = -1 and (upper = true or upper = false) or
215-
upd.getDefiningExpr().(PreDecExpr).getExpr() = e and delta = -1 and (upper = true or upper = false) or
216-
upd.getDefiningExpr().(AssignOp) = e and delta = 0 and (upper = true or upper = false)
217-
) or
193+
ssaUpdateStep(v, e, delta) and pos.hasReadOfVar(v) and (upper = true or upper = false) and reason = TNoReason()
194+
or
218195
exists(Guard guard, boolean testIsTrue |
219196
pos.hasReadOfVar(v) and
220197
guard = boundFlowCond(v, e, delta, upper, testIsTrue) and
@@ -291,31 +268,16 @@ private class NarrowingCastExpr extends CastExpr {
291268
* - `upper = false` : `e2 >= e1 + delta`
292269
*/
293270
private predicate boundFlowStep(Expr e2, Expr e1, int delta, boolean upper) {
294-
e2.(ParExpr).getExpr() = e1 and delta = 0 and (upper = true or upper = false) or
295-
e2.(AssignExpr).getSource() = e1 and delta = 0 and (upper = true or upper = false) or
296-
e2.(PlusExpr).getExpr() = e1 and delta = 0 and (upper = true or upper = false) or
297-
e2.(PostIncExpr).getExpr() = e1 and delta = 0 and (upper = true or upper = false) or
298-
e2.(PostDecExpr).getExpr() = e1 and delta = 0 and (upper = true or upper = false) or
299-
e2.(PreIncExpr).getExpr() = e1 and delta = 1 and (upper = true or upper = false) or
300-
e2.(PreDecExpr).getExpr() = e1 and delta = -1 and (upper = true or upper = false) or
271+
valueFlowStep(e2, e1, delta) and (upper = true or upper = false) or
301272
e2.(SafeCastExpr).getExpr() = e1 and delta = 0 and (upper = true or upper = false) or
302-
exists(SsaExplicitUpdate v, FieldRead arrlen |
303-
e2 = arrlen and
304-
arrlen.getField() instanceof ArrayLengthField and
305-
arrlen.getQualifier() = v.getAUse() and
306-
v.getDefiningExpr().(VariableAssign).getSource().(ArrayCreationExpr).getDimension(0) = e1 and
307-
delta = 0 and
308-
(upper = true or upper = false)
309-
) or
310273
exists(Expr x |
311274
e2.(AddExpr).hasOperands(e1, x) or
312275
exists(AssignAddExpr add | add = e2 |
313276
add.getDest() = e1 and add.getRhs() = x or
314277
add.getDest() = x and add.getRhs() = e1
315278
)
316279
|
317-
x.(ConstantIntegerExpr).getIntValue() = delta and (upper = true or upper = false)
318-
or
280+
// `x instanceof ConstantIntegerExpr` is covered by valueFlowStep
319281
not x instanceof ConstantIntegerExpr and
320282
not e1 instanceof ConstantIntegerExpr and
321283
if strictlyPositive(x) then
@@ -341,8 +303,7 @@ private predicate boundFlowStep(Expr e2, Expr e1, int delta, boolean upper) {
341303
sub.getRhs() = x
342304
)
343305
|
344-
x.(ConstantIntegerExpr).getIntValue() = -delta and (upper = true or upper = false)
345-
or
306+
// `x instanceof ConstantIntegerExpr` is covered by valueFlowStep
346307
not x instanceof ConstantIntegerExpr and
347308
if strictlyPositive(x) then
348309
(upper = true and delta = -1)

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

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,75 @@ predicate guardControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean
138138
guardControlsSsaRead(guard0, controlled, testIsTrue0)
139139
)
140140
}
141+
142+
/**
143+
* Gets a condition that tests whether `v` equals `e + delta`.
144+
*
145+
* If the condition evaluates to `testIsTrue`:
146+
* - `isEq = true` : `v == e + delta`
147+
* - `isEq = false` : `v != e + delta`
148+
*/
149+
Guard eqFlowCond(SsaVariable v, Expr e, int delta, boolean isEq, boolean testIsTrue) {
150+
exists(boolean eqpolarity |
151+
result.isEquality(ssaRead(v, delta), e, eqpolarity) and
152+
(testIsTrue = true or testIsTrue = false) and
153+
eqpolarity.booleanXor(testIsTrue).booleanNot() = isEq
154+
)
155+
or
156+
exists(boolean testIsTrue0 | implies_v2(result, testIsTrue, eqFlowCond(v, e, delta, isEq, testIsTrue0), testIsTrue0))
157+
}
158+
159+
/**
160+
* Holds if `v` is an `SsaExplicitUpdate` that equals `e + delta`.
161+
*/
162+
predicate ssaUpdateStep(SsaExplicitUpdate v, Expr e, int delta) {
163+
v.getDefiningExpr().(VariableAssign).getSource() = e and delta = 0 or
164+
v.getDefiningExpr().(PostIncExpr).getExpr() = e and delta = 1 or
165+
v.getDefiningExpr().(PreIncExpr).getExpr() = e and delta = 1 or
166+
v.getDefiningExpr().(PostDecExpr).getExpr() = e and delta = -1 or
167+
v.getDefiningExpr().(PreDecExpr).getExpr() = e and delta = -1 or
168+
v.getDefiningExpr().(AssignOp) = e and delta = 0
169+
}
170+
171+
/**
172+
* Holds if `e1 + delta` equals `e2`.
173+
*/
174+
predicate valueFlowStep(Expr e2, Expr e1, int delta) {
175+
e2.(ParExpr).getExpr() = e1 and delta = 0 or
176+
e2.(AssignExpr).getSource() = e1 and delta = 0 or
177+
e2.(PlusExpr).getExpr() = e1 and delta = 0 or
178+
e2.(PostIncExpr).getExpr() = e1 and delta = 0 or
179+
e2.(PostDecExpr).getExpr() = e1 and delta = 0 or
180+
e2.(PreIncExpr).getExpr() = e1 and delta = 1 or
181+
e2.(PreDecExpr).getExpr() = e1 and delta = -1 or
182+
exists(SsaExplicitUpdate v, FieldRead arrlen |
183+
e2 = arrlen and
184+
arrlen.getField() instanceof ArrayLengthField and
185+
arrlen.getQualifier() = v.getAUse() and
186+
v.getDefiningExpr().(VariableAssign).getSource().(ArrayCreationExpr).getDimension(0) = e1 and
187+
delta = 0
188+
) or
189+
exists(Expr x |
190+
e2.(AddExpr).hasOperands(e1, x) or
191+
exists(AssignAddExpr add | add = e2 |
192+
add.getDest() = e1 and add.getRhs() = x or
193+
add.getDest() = x and add.getRhs() = e1
194+
)
195+
|
196+
x.(ConstantIntegerExpr).getIntValue() = delta
197+
) or
198+
exists(Expr x |
199+
exists(SubExpr sub |
200+
e2 = sub and
201+
sub.getLeftOperand() = e1 and
202+
sub.getRightOperand() = x
203+
) or
204+
exists(AssignSubExpr sub |
205+
e2 = sub and
206+
sub.getDest() = e1 and
207+
sub.getRhs() = x
208+
)
209+
|
210+
x.(ConstantIntegerExpr).getIntValue() = -delta
211+
)
212+
}

0 commit comments

Comments
 (0)