Skip to content

Commit a7f3ef1

Browse files
committed
Rangeanalysis: Parameterise shared modulus analysis.
1 parent 8e2b17c commit a7f3ef1

File tree

4 files changed

+107
-100
lines changed

4 files changed

+107
-100
lines changed

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisImpl.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ module Sem implements Semantic {
7878

7979
predicate guardDirectlyControlsSsaRead = semGuardDirectlyControlsSsaRead/3;
8080

81+
predicate guardControlsSsaRead = semGuardControlsSsaRead/3;
82+
8183
class Type = SemType;
8284

8385
class IntegerType = SemIntegerType;

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ module Sem implements Semantic {
224224
RU::guardDirectlyControlsSsaRead(guard, controlled, testIsTrue)
225225
}
226226

227+
predicate guardControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) {
228+
RU::guardControlsSsaRead(guard, controlled, testIsTrue)
229+
}
230+
227231
class Type = J::Type;
228232

229233
class IntegerType extends J::IntegralType {

shared/rangeanalysis/codeql/rangeanalysis/ModulusAnalysis.qll

Lines changed: 95 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,30 @@
1010
* handles phi inputs.
1111
*/
1212

13-
private import ModulusAnalysisSpecific::Private
14-
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
15-
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticLocation
16-
private import ConstantAnalysis
17-
private import RangeUtils
18-
private import codeql.rangeanalysis.RangeAnalysis
19-
private import RangeAnalysisImpl
13+
private import codeql.util.Location
14+
private import RangeAnalysis
2015

21-
module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig<Sem, D> U> {
16+
module ModulusAnalysis<
17+
LocationSig Location, Semantic Sem, DeltaSig D, BoundSig<Location, Sem, D> Bounds,
18+
UtilSig<Sem, D> U>
19+
{
2220
pragma[nomagic]
2321
private predicate valueFlowStepSsaEqFlowCond(
24-
SemSsaReadPosition pos, SemSsaVariable v, SemExpr e, int delta
22+
Sem::SsaReadPosition pos, Sem::SsaVariable v, Sem::Expr e, int delta
2523
) {
26-
exists(SemGuard guard, boolean testIsTrue |
24+
exists(Sem::Guard guard, boolean testIsTrue |
2725
guard = U::semEqFlowCond(v, e, D::fromInt(delta), true, testIsTrue) and
28-
semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue)
26+
Sem::guardDirectlyControlsSsaRead(guard, pos, testIsTrue)
2927
)
3028
}
3129

3230
/**
3331
* Holds if `e + delta` equals `v` at `pos`.
3432
*/
3533
pragma[nomagic]
36-
private predicate valueFlowStepSsa(SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, int delta) {
34+
private predicate valueFlowStepSsa(
35+
Sem::SsaVariable v, Sem::SsaReadPosition pos, Sem::Expr e, int delta
36+
) {
3737
U::semSsaUpdateStep(v, e, D::fromInt(delta)) and pos.hasReadOfVar(v)
3838
or
3939
pos.hasReadOfVar(v) and
@@ -44,49 +44,49 @@ module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig
4444
* Holds if `add` is the addition of `larg` and `rarg`, neither of which are
4545
* `ConstantIntegerExpr`s.
4646
*/
47-
private predicate nonConstAddition(SemExpr add, SemExpr larg, SemExpr rarg) {
48-
exists(SemAddExpr a | a = add |
47+
private predicate nonConstAddition(Sem::Expr add, Sem::Expr larg, Sem::Expr rarg) {
48+
exists(Sem::AddExpr a | a = add |
4949
larg = a.getLeftOperand() and
5050
rarg = a.getRightOperand()
5151
) and
52-
not larg instanceof SemConstantIntegerExpr and
53-
not rarg instanceof SemConstantIntegerExpr
52+
not larg instanceof Sem::ConstantIntegerExpr and
53+
not rarg instanceof Sem::ConstantIntegerExpr
5454
}
5555

5656
/**
5757
* Holds if `sub` is the subtraction of `larg` and `rarg`, where `rarg` is not
5858
* a `ConstantIntegerExpr`.
5959
*/
60-
private predicate nonConstSubtraction(SemExpr sub, SemExpr larg, SemExpr rarg) {
61-
exists(SemSubExpr s | s = sub |
60+
private predicate nonConstSubtraction(Sem::Expr sub, Sem::Expr larg, Sem::Expr rarg) {
61+
exists(Sem::SubExpr s | s = sub |
6262
larg = s.getLeftOperand() and
6363
rarg = s.getRightOperand()
6464
) and
65-
not rarg instanceof SemConstantIntegerExpr
65+
not rarg instanceof Sem::ConstantIntegerExpr
6666
}
6767

6868
/** Gets an expression that is the remainder modulo `mod` of `arg`. */
69-
private SemExpr modExpr(SemExpr arg, int mod) {
70-
exists(SemRemExpr rem |
69+
private Sem::Expr modExpr(Sem::Expr arg, int mod) {
70+
exists(Sem::RemExpr rem |
7171
result = rem and
7272
arg = rem.getLeftOperand() and
73-
rem.getRightOperand().(SemConstantIntegerExpr).getIntValue() = mod and
73+
rem.getRightOperand().(Sem::ConstantIntegerExpr).getIntValue() = mod and
7474
mod >= 2
7575
)
7676
or
77-
exists(SemConstantIntegerExpr c |
77+
exists(Sem::ConstantIntegerExpr c |
7878
mod = 2.pow([1 .. 30]) and
7979
c.getIntValue() = mod - 1 and
80-
result.(SemBitAndExpr).hasOperands(arg, c)
80+
result.(Sem::BitAndExpr).hasOperands(arg, c)
8181
)
8282
}
8383

8484
/**
8585
* Gets a guard that tests whether `v` is congruent with `val` modulo `mod` on
8686
* its `testIsTrue` branch.
8787
*/
88-
private SemGuard moduloCheck(SemSsaVariable v, int val, int mod, boolean testIsTrue) {
89-
exists(SemExpr rem, SemConstantIntegerExpr c, int r, boolean polarity |
88+
private Sem::Guard moduloCheck(Sem::SsaVariable v, int val, int mod, boolean testIsTrue) {
89+
exists(Sem::Expr rem, Sem::ConstantIntegerExpr c, int r, boolean polarity |
9090
result.isEquality(rem, c, polarity) and
9191
c.getIntValue() = r and
9292
rem = modExpr(v.getAUse(), mod) and
@@ -104,11 +104,11 @@ module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig
104104
/**
105105
* Holds if a guard ensures that `v` at `pos` is congruent with `val` modulo `mod`.
106106
*/
107-
private predicate moduloGuardedRead(SemSsaVariable v, SemSsaReadPosition pos, int val, int mod) {
108-
exists(SemGuard guard, boolean testIsTrue |
107+
private predicate moduloGuardedRead(Sem::SsaVariable v, Sem::SsaReadPosition pos, int val, int mod) {
108+
exists(Sem::Guard guard, boolean testIsTrue |
109109
pos.hasReadOfVar(v) and
110110
guard = moduloCheck(v, val, mod, testIsTrue) and
111-
semGuardControlsSsaRead(guard, pos, testIsTrue)
111+
Sem::guardControlsSsaRead(guard, pos, testIsTrue)
112112
)
113113
}
114114

@@ -120,13 +120,13 @@ module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig
120120
}
121121

122122
/** Holds if `e` is evenly divisible by `factor`. */
123-
private predicate evenlyDivisibleExpr(SemExpr e, int factor) {
124-
exists(SemConstantIntegerExpr c, int k | k = c.getIntValue() |
125-
e.(SemMulExpr).getAnOperand() = c and factor = k.abs() and factor >= 2
123+
private predicate evenlyDivisibleExpr(Sem::Expr e, int factor) {
124+
exists(Sem::ConstantIntegerExpr c, int k | k = c.getIntValue() |
125+
e.(Sem::MulExpr).getAnOperand() = c and factor = k.abs() and factor >= 2
126126
or
127-
e.(SemShiftLeftExpr).getRightOperand() = c and factor = 2.pow(k) and k > 0
127+
e.(Sem::ShiftLeftExpr).getRightOperand() = c and factor = 2.pow(k) and k > 0
128128
or
129-
e.(SemBitAndExpr).getAnOperand() = c and factor = max(int f | andmaskFactor(k, f))
129+
e.(Sem::BitAndExpr).getAnOperand() = c and factor = max(int f | andmaskFactor(k, f))
130130
)
131131
}
132132

@@ -147,7 +147,7 @@ module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig
147147
* Holds if `inp` is an input to `phi` and equals `phi` modulo `mod` along `edge`.
148148
*/
149149
private predicate phiSelfModulus(
150-
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int mod
150+
Sem::SsaPhiNode phi, Sem::SsaVariable inp, Sem::SsaReadPositionPhiInputEdge edge, int mod
151151
) {
152152
exists(Bounds::SemSsaBound phibound, int v, int m |
153153
edge.phiInput(phi, inp) and
@@ -161,8 +161,8 @@ module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig
161161
/**
162162
* Holds if `b + val` modulo `mod` is a candidate congruence class for `phi`.
163163
*/
164-
private predicate phiModulusInit(SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod) {
165-
exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge |
164+
private predicate phiModulusInit(Sem::SsaPhiNode phi, Bounds::SemBound b, int val, int mod) {
165+
exists(Sem::SsaVariable inp, Sem::SsaReadPositionPhiInputEdge edge |
166166
edge.phiInput(phi, inp) and
167167
ssaModulus(inp, edge, b, val, mod)
168168
)
@@ -173,7 +173,7 @@ module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig
173173
*/
174174
pragma[nomagic]
175175
private predicate phiModulusRankStep(
176-
SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod, int rix
176+
Sem::SsaPhiNode phi, Bounds::SemBound b, int val, int mod, int rix
177177
) {
178178
/*
179179
* base case. If any phi input is equal to `b + val` modulo `mod`, that's a potential congruence
@@ -183,7 +183,7 @@ module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig
183183
rix = 0 and
184184
phiModulusInit(phi, b, val, mod)
185185
or
186-
exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int v1, int m1 |
186+
exists(Sem::SsaVariable inp, Sem::SsaReadPositionPhiInputEdge edge, int v1, int m1 |
187187
mod != 1 and
188188
val = remainder(v1, mod)
189189
|
@@ -194,7 +194,7 @@ module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig
194194
*/
195195

196196
exists(int v2, int m2 |
197-
rankedPhiInput(pragma[only_bind_out](phi), inp, edge, rix) and
197+
U::rankedPhiInput(pragma[only_bind_out](phi), inp, edge, rix) and
198198
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
199199
ssaModulus(inp, edge, b, v2, m2) and
200200
mod = m1.gcd(m2).gcd(v1 - v2)
@@ -207,7 +207,7 @@ module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig
207207
*/
208208

209209
exists(int m2 |
210-
rankedPhiInput(phi, inp, edge, rix) and
210+
U::rankedPhiInput(phi, inp, edge, rix) and
211211
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
212212
phiSelfModulus(phi, inp, edge, m2) and
213213
mod = m1.gcd(m2)
@@ -218,9 +218,9 @@ module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig
218218
/**
219219
* Holds if `phi` is equal to `b + val` modulo `mod`.
220220
*/
221-
private predicate phiModulus(SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod) {
221+
private predicate phiModulus(Sem::SsaPhiNode phi, Bounds::SemBound b, int val, int mod) {
222222
exists(int r |
223-
maxPhiInputRank(phi, r) and
223+
U::maxPhiInputRank(phi, r) and
224224
phiModulusRankStep(phi, b, val, mod, r)
225225
)
226226
}
@@ -229,13 +229,13 @@ module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig
229229
* Holds if `v` at `pos` is equal to `b + val` modulo `mod`.
230230
*/
231231
private predicate ssaModulus(
232-
SemSsaVariable v, SemSsaReadPosition pos, Bounds::SemBound b, int val, int mod
232+
Sem::SsaVariable v, Sem::SsaReadPosition pos, Bounds::SemBound b, int val, int mod
233233
) {
234234
phiModulus(v, b, val, mod) and pos.hasReadOfVar(v)
235235
or
236236
b.(Bounds::SemSsaBound).getVariable() = v and pos.hasReadOfVar(v) and val = 0 and mod = 0
237237
or
238-
exists(SemExpr e, int val0, int delta |
238+
exists(Sem::Expr e, int val0, int delta |
239239
semExprModulus(e, b, val0, mod) and
240240
valueFlowStepSsa(v, pos, e, delta) and
241241
val = remainder(val0 + delta, mod)
@@ -252,74 +252,71 @@ module ModulusAnalysis<DeltaSig D, BoundSig<SemLocation, Sem, D> Bounds, UtilSig
252252
* - `mod > 1`: `val` lies within the range `[0 .. mod-1]`.
253253
*/
254254
cached
255-
predicate semExprModulus(SemExpr e, Bounds::SemBound b, int val, int mod) {
256-
not ignoreExprModulus(e) and
257-
(
258-
e = b.getExpr(D::fromInt(val)) and mod = 0
259-
or
260-
evenlyDivisibleExpr(e, mod) and
261-
val = 0 and
262-
b instanceof Bounds::SemZeroBound
263-
or
264-
exists(SemSsaVariable v, SemSsaReadPositionBlock bb |
265-
ssaModulus(v, bb, b, val, mod) and
266-
e = v.getAUse() and
267-
bb.getAnExpr() = e
268-
)
269-
or
270-
exists(SemExpr mid, int val0, int delta |
271-
semExprModulus(mid, b, val0, mod) and
272-
U::semValueFlowStep(e, mid, D::fromInt(delta)) and
273-
val = remainder(val0 + delta, mod)
274-
)
275-
or
276-
exists(SemConditionalExpr cond, int v1, int v2, int m1, int m2 |
277-
cond = e and
278-
condExprBranchModulus(cond, true, b, v1, m1) and
279-
condExprBranchModulus(cond, false, b, v2, m2) and
280-
mod = m1.gcd(m2).gcd(v1 - v2) and
281-
mod != 1 and
282-
val = remainder(v1, mod)
283-
)
284-
or
285-
exists(Bounds::SemBound b1, Bounds::SemBound b2, int v1, int v2, int m1, int m2 |
286-
addModulus(e, true, b1, v1, m1) and
287-
addModulus(e, false, b2, v2, m2) and
288-
mod = m1.gcd(m2) and
289-
mod != 1 and
290-
val = remainder(v1 + v2, mod)
291-
|
292-
b = b1 and b2 instanceof Bounds::SemZeroBound
293-
or
294-
b = b2 and b1 instanceof Bounds::SemZeroBound
295-
)
255+
predicate semExprModulus(Sem::Expr e, Bounds::SemBound b, int val, int mod) {
256+
e = b.getExpr(D::fromInt(val)) and mod = 0
257+
or
258+
evenlyDivisibleExpr(e, mod) and
259+
val = 0 and
260+
b instanceof Bounds::SemZeroBound
261+
or
262+
exists(Sem::SsaVariable v, Sem::SsaReadPositionBlock bb |
263+
ssaModulus(v, bb, b, val, mod) and
264+
e = v.getAUse() and
265+
bb.getBlock() = e.getBasicBlock()
266+
)
267+
or
268+
exists(Sem::Expr mid, int val0, int delta |
269+
semExprModulus(mid, b, val0, mod) and
270+
U::semValueFlowStep(e, mid, D::fromInt(delta)) and
271+
val = remainder(val0 + delta, mod)
272+
)
273+
or
274+
exists(Sem::ConditionalExpr cond, int v1, int v2, int m1, int m2 |
275+
cond = e and
276+
condExprBranchModulus(cond, true, b, v1, m1) and
277+
condExprBranchModulus(cond, false, b, v2, m2) and
278+
mod = m1.gcd(m2).gcd(v1 - v2) and
279+
mod != 1 and
280+
val = remainder(v1, mod)
281+
)
282+
or
283+
exists(Bounds::SemBound b1, Bounds::SemBound b2, int v1, int v2, int m1, int m2 |
284+
addModulus(e, true, b1, v1, m1) and
285+
addModulus(e, false, b2, v2, m2) and
286+
mod = m1.gcd(m2) and
287+
mod != 1 and
288+
val = remainder(v1 + v2, mod)
289+
|
290+
b = b1 and b2 instanceof Bounds::SemZeroBound
296291
or
297-
exists(int v1, int v2, int m1, int m2 |
298-
subModulus(e, true, b, v1, m1) and
299-
subModulus(e, false, any(Bounds::SemZeroBound zb), v2, m2) and
300-
mod = m1.gcd(m2) and
301-
mod != 1 and
302-
val = remainder(v1 - v2, mod)
303-
)
292+
b = b2 and b1 instanceof Bounds::SemZeroBound
293+
)
294+
or
295+
exists(int v1, int v2, int m1, int m2 |
296+
subModulus(e, true, b, v1, m1) and
297+
subModulus(e, false, any(Bounds::SemZeroBound zb), v2, m2) and
298+
mod = m1.gcd(m2) and
299+
mod != 1 and
300+
val = remainder(v1 - v2, mod)
304301
)
305302
}
306303

307304
private predicate condExprBranchModulus(
308-
SemConditionalExpr cond, boolean branch, Bounds::SemBound b, int val, int mod
305+
Sem::ConditionalExpr cond, boolean branch, Bounds::SemBound b, int val, int mod
309306
) {
310307
semExprModulus(cond.getBranchExpr(branch), b, val, mod)
311308
}
312309

313-
private predicate addModulus(SemExpr add, boolean isLeft, Bounds::SemBound b, int val, int mod) {
314-
exists(SemExpr larg, SemExpr rarg | nonConstAddition(add, larg, rarg) |
310+
private predicate addModulus(Sem::Expr add, boolean isLeft, Bounds::SemBound b, int val, int mod) {
311+
exists(Sem::Expr larg, Sem::Expr rarg | nonConstAddition(add, larg, rarg) |
315312
semExprModulus(larg, b, val, mod) and isLeft = true
316313
or
317314
semExprModulus(rarg, b, val, mod) and isLeft = false
318315
)
319316
}
320317

321-
private predicate subModulus(SemExpr sub, boolean isLeft, Bounds::SemBound b, int val, int mod) {
322-
exists(SemExpr larg, SemExpr rarg | nonConstSubtraction(sub, larg, rarg) |
318+
private predicate subModulus(Sem::Expr sub, boolean isLeft, Bounds::SemBound b, int val, int mod) {
319+
exists(Sem::Expr larg, Sem::Expr rarg | nonConstSubtraction(sub, larg, rarg) |
323320
semExprModulus(larg, b, val, mod) and isLeft = true
324321
or
325322
semExprModulus(rarg, b, val, mod) and isLeft = false

0 commit comments

Comments
 (0)