Skip to content

Commit 75f825e

Browse files
committed
csharp/ql/lib: update shared rangeanalysis library to use BigInts
1 parent 3e1ca9b commit 75f825e

File tree

6 files changed

+136
-95
lines changed

6 files changed

+136
-95
lines changed

csharp/ql/lib/semmle/code/csharp/dataflow/Bound.qll

+11-5
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ abstract class Bound extends TBound {
2020
abstract string toString();
2121

2222
/** Gets an expression that equals this bound plus `delta`. */
23-
abstract Expr getExpr(int delta);
23+
abstract Expr getExpr(QlBuiltins::BigInt delta);
2424

2525
/** Gets an expression that equals this bound. */
26-
Expr getExpr() { result = this.getExpr(0) }
26+
Expr getExpr() { result = this.getExpr(0.toBigInt()) }
2727

2828
/** Gets the location of this bound. */
2929
abstract Location getLocation();
@@ -36,7 +36,9 @@ abstract class Bound extends TBound {
3636
class ZeroBound extends Bound, TBoundZero {
3737
override string toString() { result = "0" }
3838

39-
override Expr getExpr(int delta) { result.(ConstantIntegerExpr).getIntValue() = delta }
39+
override Expr getExpr(QlBuiltins::BigInt delta) {
40+
result.(ConstantIntegerExpr).getIntValue() = delta
41+
}
4042

4143
override Location getLocation() { result.hasLocationInfo("", 0, 0, 0, 0) }
4244
}
@@ -50,7 +52,9 @@ class SsaBound extends Bound, TBoundSsa {
5052

5153
override string toString() { result = this.getSsa().toString() }
5254

53-
override Expr getExpr(int delta) { result = this.getSsa().getAUse() and delta = 0 }
55+
override Expr getExpr(QlBuiltins::BigInt delta) {
56+
result = this.getSsa().getAUse() and delta = 0.toBigInt()
57+
}
5458

5559
override Location getLocation() { result = this.getSsa().getLocation() }
5660
}
@@ -62,7 +66,9 @@ class SsaBound extends Bound, TBoundSsa {
6266
class ExprBound extends Bound, TBoundExpr {
6367
override string toString() { result = this.getExpr().toString() }
6468

65-
override Expr getExpr(int delta) { this = TBoundExpr(result) and delta = 0 }
69+
override Expr getExpr(QlBuiltins::BigInt delta) {
70+
this = TBoundExpr(result) and delta = 0.toBigInt()
71+
}
6672

6773
override Location getLocation() { result = this.getExpr().getLocation() }
6874
}

csharp/ql/lib/semmle/code/csharp/dataflow/ModulusAnalysis.qll

+72-45
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ private import internal.rangeanalysis.SsaReadPositionCommon
1111
/**
1212
* Holds if `e + delta` equals `v` at `pos`.
1313
*/
14-
private predicate valueFlowStepSsa(SsaVariable v, SsaReadPosition pos, Expr e, int delta) {
14+
private predicate valueFlowStepSsa(
15+
SsaVariable v, SsaReadPosition pos, Expr e, QlBuiltins::BigInt delta
16+
) {
1517
ssaUpdateStep(v, e, delta) and pos.hasReadOfVar(v)
1618
or
1719
exists(Guard guard, boolean testIsTrue |
@@ -47,17 +49,17 @@ private predicate nonConstSubtraction(Expr sub, Expr larg, Expr rarg) {
4749
}
4850

4951
/** Gets an expression that is the remainder modulo `mod` of `arg`. */
50-
private Expr modExpr(Expr arg, int mod) {
52+
private Expr modExpr(Expr arg, QlBuiltins::BigInt mod) {
5153
exists(RemExpr rem |
5254
result = rem and
5355
arg = rem.getLeftOperand() and
5456
rem.getRightOperand().(ConstantIntegerExpr).getIntValue() = mod and
55-
mod >= 2
57+
mod >= 2.toBigInt()
5658
)
5759
or
5860
exists(ConstantIntegerExpr c |
59-
mod = 2.pow([1 .. 30]) and
60-
c.getIntValue() = mod - 1 and
61+
mod = 2.toBigInt().pow([1 .. 30]) and
62+
c.getIntValue() = mod - 1.toBigInt() and
6163
result.(BitwiseAndExpr).hasOperands(arg, c)
6264
)
6365
}
@@ -66,26 +68,30 @@ private Expr modExpr(Expr arg, int mod) {
6668
* Gets a guard that tests whether `v` is congruent with `val` modulo `mod` on
6769
* its `testIsTrue` branch.
6870
*/
69-
private Guard moduloCheck(SsaVariable v, int val, int mod, boolean testIsTrue) {
70-
exists(Expr rem, ConstantIntegerExpr c, int r, boolean polarity |
71+
private Guard moduloCheck(
72+
SsaVariable v, QlBuiltins::BigInt val, QlBuiltins::BigInt mod, boolean testIsTrue
73+
) {
74+
exists(Expr rem, ConstantIntegerExpr c, QlBuiltins::BigInt r, boolean polarity |
7175
result.isEquality(rem, c, polarity) and
7276
c.getIntValue() = r and
7377
rem = modExpr(v.getAUse(), mod) and
7478
(
7579
testIsTrue = polarity and val = r
7680
or
7781
testIsTrue = polarity.booleanNot() and
78-
mod = 2 and
79-
val = 1 - r and
80-
(r = 0 or r = 1)
82+
mod = 2.toBigInt() and
83+
val = 1.toBigInt() - r and
84+
(r = 0.toBigInt() or r = 1.toBigInt())
8185
)
8286
)
8387
}
8488

8589
/**
8690
* Holds if a guard ensures that `v` at `pos` is congruent with `val` modulo `mod`.
8791
*/
88-
private predicate moduloGuardedRead(SsaVariable v, SsaReadPosition pos, int val, int mod) {
92+
private predicate moduloGuardedRead(
93+
SsaVariable v, SsaReadPosition pos, QlBuiltins::BigInt val, QlBuiltins::BigInt mod
94+
) {
8995
exists(Guard guard, boolean testIsTrue |
9096
pos.hasReadOfVar(v) and
9197
guard = moduloCheck(v, val, mod, testIsTrue) and
@@ -101,13 +107,14 @@ private predicate andmaskFactor(int mask, int factor) {
101107
}
102108

103109
/** Holds if `e` is evenly divisible by `factor`. */
104-
private predicate evenlyDivisibleExpr(Expr e, int factor) {
105-
exists(ConstantIntegerExpr c, int k | k = c.getIntValue() |
106-
e.(MulExpr).getAnOperand() = c and factor = k.abs() and factor >= 2
110+
private predicate evenlyDivisibleExpr(Expr e, QlBuiltins::BigInt factor) {
111+
exists(ConstantIntegerExpr c, QlBuiltins::BigInt k | k = c.getIntValue() |
112+
e.(MulExpr).getAnOperand() = c and factor = k.abs() and factor >= 2.toBigInt()
107113
or
108-
e.(LeftShiftExpr).getRhs() = c and factor = 2.pow(k) and k > 0
114+
e.(LeftShiftExpr).getRhs() = c and factor = 2.toBigInt().pow(k.toInt()) and k > 0.toBigInt()
109115
or
110-
e.(BitwiseAndExpr).getAnOperand() = c and factor = max(int f | andmaskFactor(k, f))
116+
e.(BitwiseAndExpr).getAnOperand() = c and
117+
factor = max(int f | andmaskFactor(k.toInt(), f)).toBigInt()
111118
)
112119
}
113120

@@ -118,31 +125,33 @@ private predicate evenlyDivisibleExpr(Expr e, int factor) {
118125
* the range `[0 .. mod-1]`.
119126
*/
120127
bindingset[val, mod]
121-
private int remainder(int val, int mod) {
122-
mod = 0 and result = val
128+
private QlBuiltins::BigInt remainder(QlBuiltins::BigInt val, QlBuiltins::BigInt mod) {
129+
mod = 0.toBigInt() and result = val
123130
or
124-
mod > 1 and result = ((val % mod) + mod) % mod
131+
mod > 1.toBigInt() and result = ((val % mod) + mod) % mod
125132
}
126133

127134
/**
128135
* Holds if `inp` is an input to `phi` and equals `phi` modulo `mod` along `edge`.
129136
*/
130137
private predicate phiSelfModulus(
131-
SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge, int mod
138+
SsaPhiNode phi, SsaVariable inp, SsaReadPositionPhiInputEdge edge, QlBuiltins::BigInt mod
132139
) {
133-
exists(SsaBound phibound, int v, int m |
140+
exists(SsaBound phibound, QlBuiltins::BigInt v, QlBuiltins::BigInt m |
134141
edge.phiInput(phi, inp) and
135142
phibound.getSsa() = phi and
136143
ssaModulus(inp, edge, phibound, v, m) and
137144
mod = m.gcd(v) and
138-
mod != 1
145+
mod != 1.toBigInt()
139146
)
140147
}
141148

142149
/**
143150
* Holds if `b + val` modulo `mod` is a candidate congruence class for `phi`.
144151
*/
145-
private predicate phiModulusInit(SsaPhiNode phi, Bound b, int val, int mod) {
152+
private predicate phiModulusInit(
153+
SsaPhiNode phi, Bound b, QlBuiltins::BigInt val, QlBuiltins::BigInt mod
154+
) {
146155
exists(SsaVariable inp, SsaReadPositionPhiInputEdge edge |
147156
edge.phiInput(phi, inp) and
148157
ssaModulus(inp, edge, b, val, mod)
@@ -152,22 +161,26 @@ private predicate phiModulusInit(SsaPhiNode phi, Bound b, int val, int mod) {
152161
/**
153162
* Holds if all inputs to `phi` numbered `1` to `rix` are equal to `b + val` modulo `mod`.
154163
*/
155-
private predicate phiModulusRankStep(SsaPhiNode phi, Bound b, int val, int mod, int rix) {
164+
private predicate phiModulusRankStep(
165+
SsaPhiNode phi, Bound b, QlBuiltins::BigInt val, QlBuiltins::BigInt mod, int rix
166+
) {
156167
rix = 0 and
157168
phiModulusInit(phi, b, val, mod)
158169
or
159-
exists(SsaVariable inp, SsaReadPositionPhiInputEdge edge, int v1, int m1 |
160-
mod != 1 and
170+
exists(
171+
SsaVariable inp, SsaReadPositionPhiInputEdge edge, QlBuiltins::BigInt v1, QlBuiltins::BigInt m1
172+
|
173+
mod != 1.toBigInt() and
161174
val = remainder(v1, mod)
162175
|
163-
exists(int v2, int m2 |
176+
exists(QlBuiltins::BigInt v2, QlBuiltins::BigInt m2 |
164177
rankedPhiInput(phi, inp, edge, rix) and
165178
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
166179
ssaModulus(inp, edge, b, v2, m2) and
167180
mod = m1.gcd(m2).gcd(v1 - v2)
168181
)
169182
or
170-
exists(int m2 |
183+
exists(QlBuiltins::BigInt m2 |
171184
rankedPhiInput(phi, inp, edge, rix) and
172185
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
173186
phiSelfModulus(phi, inp, edge, m2) and
@@ -179,7 +192,7 @@ private predicate phiModulusRankStep(SsaPhiNode phi, Bound b, int val, int mod,
179192
/**
180193
* Holds if `phi` is equal to `b + val` modulo `mod`.
181194
*/
182-
private predicate phiModulus(SsaPhiNode phi, Bound b, int val, int mod) {
195+
private predicate phiModulus(SsaPhiNode phi, Bound b, QlBuiltins::BigInt val, QlBuiltins::BigInt mod) {
183196
exists(int r |
184197
maxPhiInputRank(phi, r) and
185198
phiModulusRankStep(phi, b, val, mod, r)
@@ -189,12 +202,14 @@ private predicate phiModulus(SsaPhiNode phi, Bound b, int val, int mod) {
189202
/**
190203
* Holds if `v` at `pos` is equal to `b + val` modulo `mod`.
191204
*/
192-
private predicate ssaModulus(SsaVariable v, SsaReadPosition pos, Bound b, int val, int mod) {
205+
private predicate ssaModulus(
206+
SsaVariable v, SsaReadPosition pos, Bound b, QlBuiltins::BigInt val, QlBuiltins::BigInt mod
207+
) {
193208
phiModulus(v, b, val, mod) and pos.hasReadOfVar(v)
194209
or
195-
b.(SsaBound).getSsa() = v and pos.hasReadOfVar(v) and val = 0 and mod = 0
210+
b.(SsaBound).getSsa() = v and pos.hasReadOfVar(v) and val = 0.toBigInt() and mod = 0.toBigInt()
196211
or
197-
exists(Expr e, int val0, int delta |
212+
exists(Expr e, QlBuiltins::BigInt val0, QlBuiltins::BigInt delta |
198213
exprModulus(e, b, val0, mod) and
199214
valueFlowStepSsa(v, pos, e, delta) and
200215
val = remainder(val0 + delta, mod)
@@ -211,68 +226,80 @@ private predicate ssaModulus(SsaVariable v, SsaReadPosition pos, Bound b, int va
211226
* - `mod > 1`: `val` lies within the range `[0 .. mod-1]`.
212227
*/
213228
cached
214-
predicate exprModulus(Expr e, Bound b, int val, int mod) {
215-
e = b.getExpr(val) and mod = 0
229+
predicate exprModulus(Expr e, Bound b, QlBuiltins::BigInt val, QlBuiltins::BigInt mod) {
230+
e = b.getExpr(val) and mod = 0.toBigInt()
216231
or
217-
evenlyDivisibleExpr(e, mod) and val = 0 and b instanceof ZeroBound
232+
evenlyDivisibleExpr(e, mod) and val = 0.toBigInt() and b instanceof ZeroBound
218233
or
219234
exists(SsaVariable v, SsaReadPositionBlock bb |
220235
ssaModulus(v, bb, b, val, mod) and
221236
e = v.getAUse() and
222237
getABasicBlockExpr(bb.getBlock()) = e
223238
)
224239
or
225-
exists(Expr mid, int val0, int delta |
240+
exists(Expr mid, QlBuiltins::BigInt val0, QlBuiltins::BigInt delta |
226241
exprModulus(mid, b, val0, mod) and
227242
valueFlowStep(e, mid, delta) and
228243
val = remainder(val0 + delta, mod)
229244
)
230245
or
231-
exists(ConditionalExpr cond, int v1, int v2, int m1, int m2 |
246+
exists(
247+
ConditionalExpr cond, QlBuiltins::BigInt v1, QlBuiltins::BigInt v2, QlBuiltins::BigInt m1,
248+
QlBuiltins::BigInt m2
249+
|
232250
cond = e and
233251
condExprBranchModulus(cond, true, b, v1, m1) and
234252
condExprBranchModulus(cond, false, b, v2, m2) and
235253
mod = m1.gcd(m2).gcd(v1 - v2) and
236-
mod != 1 and
254+
mod != 1.toBigInt() and
237255
val = remainder(v1, mod)
238256
)
239257
or
240-
exists(Bound b1, Bound b2, int v1, int v2, int m1, int m2 |
258+
exists(
259+
Bound b1, Bound b2, QlBuiltins::BigInt v1, QlBuiltins::BigInt v2, QlBuiltins::BigInt m1,
260+
QlBuiltins::BigInt m2
261+
|
241262
addModulus(e, true, b1, v1, m1) and
242263
addModulus(e, false, b2, v2, m2) and
243264
mod = m1.gcd(m2) and
244-
mod != 1 and
265+
mod != 1.toBigInt() and
245266
val = remainder(v1 + v2, mod)
246267
|
247268
b = b1 and b2 instanceof ZeroBound
248269
or
249270
b = b2 and b1 instanceof ZeroBound
250271
)
251272
or
252-
exists(int v1, int v2, int m1, int m2 |
273+
exists(
274+
QlBuiltins::BigInt v1, QlBuiltins::BigInt v2, QlBuiltins::BigInt m1, QlBuiltins::BigInt m2
275+
|
253276
subModulus(e, true, b, v1, m1) and
254277
subModulus(e, false, any(ZeroBound zb), v2, m2) and
255278
mod = m1.gcd(m2) and
256-
mod != 1 and
279+
mod != 1.toBigInt() and
257280
val = remainder(v1 - v2, mod)
258281
)
259282
}
260283

261284
private predicate condExprBranchModulus(
262-
ConditionalExpr cond, boolean branch, Bound b, int val, int mod
285+
ConditionalExpr cond, boolean branch, Bound b, QlBuiltins::BigInt val, QlBuiltins::BigInt mod
263286
) {
264287
exprModulus(cond.getBranchExpr(branch), b, val, mod)
265288
}
266289

267-
private predicate addModulus(Expr add, boolean isLeft, Bound b, int val, int mod) {
290+
private predicate addModulus(
291+
Expr add, boolean isLeft, Bound b, QlBuiltins::BigInt val, QlBuiltins::BigInt mod
292+
) {
268293
exists(Expr larg, Expr rarg | nonConstAddition(add, larg, rarg) |
269294
exprModulus(larg, b, val, mod) and isLeft = true
270295
or
271296
exprModulus(rarg, b, val, mod) and isLeft = false
272297
)
273298
}
274299

275-
private predicate subModulus(Expr sub, boolean isLeft, Bound b, int val, int mod) {
300+
private predicate subModulus(
301+
Expr sub, boolean isLeft, Bound b, QlBuiltins::BigInt val, QlBuiltins::BigInt mod
302+
) {
276303
exists(Expr larg, Expr rarg | nonConstSubtraction(sub, larg, rarg) |
277304
exprModulus(larg, b, val, mod) and isLeft = true
278305
or

csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/ConstantUtils.qll

+12-11
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ predicate systemArrayLengthAccess(PropertyAccess pa) {
2222
* - a read of a compile time constant with integer value `val`, or
2323
* - a read of the `Length` of an array with `val` lengths.
2424
*/
25-
private predicate constantIntegerExpr(ExprNode e, int val) {
26-
e.getValue().toInt() = val
25+
private predicate constantIntegerExpr(ExprNode e, QlBuiltins::BigInt val) {
26+
e.getValue().toBigInt() = val
2727
or
2828
exists(ExprNode src |
2929
e = getAnExplicitDefinitionRead(src) and
@@ -33,25 +33,26 @@ private predicate constantIntegerExpr(ExprNode e, int val) {
3333
isArrayLengthAccess(e, val)
3434
}
3535

36-
private int getArrayLength(ExprNode e, int index) {
36+
private QlBuiltins::BigInt getArrayLength(ExprNode e, QlBuiltins::BigInt index) {
3737
exists(ArrayCreation arrCreation, ExprNode length |
38-
hasChild(arrCreation, arrCreation.getLengthArgument(index), e, length) and
38+
hasChild(arrCreation, arrCreation.getLengthArgument(any(int i | i.toBigInt() = index)), e,
39+
length) and
3940
constantIntegerExpr(length, result)
4041
)
4142
}
4243

43-
private int getArrayLengthRec(ExprNode arrCreation, int index) {
44-
index = 0 and result = getArrayLength(arrCreation, 0)
44+
private QlBuiltins::BigInt getArrayLengthRec(ExprNode arrCreation, QlBuiltins::BigInt index) {
45+
index = 0.toBigInt() and result = getArrayLength(arrCreation, 0.toBigInt())
4546
or
46-
index > 0 and
47-
result = getArrayLength(arrCreation, index) * getArrayLengthRec(arrCreation, index - 1)
47+
index > 0.toBigInt() and
48+
result = getArrayLength(arrCreation, index) * getArrayLengthRec(arrCreation, index - 1.toBigInt())
4849
}
4950

50-
private predicate isArrayLengthAccess(ExprNode e, int length) {
51+
private predicate isArrayLengthAccess(ExprNode e, QlBuiltins::BigInt length) {
5152
exists(PropertyAccess pa, ExprNode arrCreation |
5253
systemArrayLengthAccess(pa) and
5354
getArrayLengthRec(arrCreation,
54-
arrCreation.getExpr().(ArrayCreation).getNumberOfLengthArguments() - 1) = length and
55+
(arrCreation.getExpr().(ArrayCreation).getNumberOfLengthArguments() - 1).toBigInt()) = length and
5556
hasChild(pa, pa.getQualifier(), e, getAnExplicitDefinitionRead(arrCreation))
5657
)
5758
}
@@ -61,5 +62,5 @@ class ConstantIntegerExpr extends ExprNode {
6162
ConstantIntegerExpr() { constantIntegerExpr(this, _) }
6263

6364
/** Gets the integer value of this expression. */
64-
int getIntValue() { constantIntegerExpr(this, result) }
65+
QlBuiltins::BigInt getIntValue() { constantIntegerExpr(this, result) }
6566
}

0 commit comments

Comments
 (0)