Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit feb8a8c

Browse files
committed
JS: restrict bias to 30-bit range to avoid overflow
1 parent 20aa4e1 commit feb8a8c

1 file changed

Lines changed: 28 additions & 14 deletions

File tree

javascript/ql/src/semmle/javascript/RangeAnalysis.qll

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,26 @@ module RangeAnalysis {
119119
result = expr.flow()
120120
}
121121

122+
/**
123+
* A 30-bit integer.
124+
*
125+
* Adding two such integers is guaranteed not to overflow. We simply omit constraints
126+
* whose parameters would exceed this range.
127+
*/
128+
private class Bias extends int {
129+
bindingset[this]
130+
Bias() {
131+
-536870912 < this and this < 536870912
132+
}
133+
}
134+
122135
/**
123136
* Holds if `r` can be modelled as `r = root * sign + bias`.
124137
*
125138
* Only looks "one step", that is, does not follow data flow and does not recursively
126139
* unfold nested arithmetic expressions.
127140
*/
128-
private predicate linearDefinitionStep(DataFlow::Node r, DataFlow::Node root, int sign, int bias) {
141+
private predicate linearDefinitionStep(DataFlow::Node r, DataFlow::Node root, int sign, Bias bias) {
129142
not exists(r.asExpr().getIntValue()) and
130143
(
131144
exists (AddExpr expr | r.asExpr() = expr |
@@ -183,7 +196,7 @@ module RangeAnalysis {
183196
/**
184197
* Holds if `r` can be modelled as `r = root * sign + bias`.
185198
*/
186-
predicate linearDefinition(DataFlow::Node r, DataFlow::Node root, int sign, int bias) {
199+
predicate linearDefinition(DataFlow::Node r, DataFlow::Node root, int sign, Bias bias) {
187200
if hasUniquePredecessor(r) then
188201
linearDefinition(r.getAPredecessor(), root, sign, bias)
189202
else if linearDefinitionStep(r, _, _, _) then
@@ -202,7 +215,7 @@ module RangeAnalysis {
202215
/**
203216
* Holds if `r` can be modelled as `r = xroot * xsign + yroot * ysign + bias`.
204217
*/
205-
predicate linearDefinitionSum(DataFlow::Node r, DataFlow::Node xroot, int xsign, DataFlow::Node yroot, int ysign, int bias) {
218+
predicate linearDefinitionSum(DataFlow::Node r, DataFlow::Node xroot, int xsign, DataFlow::Node yroot, int ysign, Bias bias) {
206219
if hasUniquePredecessor(r) then
207220
linearDefinitionSum(r.getAPredecessor(), xroot, xsign, yroot, ysign, bias)
208221
else if exists(r.asExpr().getIntValue()) then
@@ -225,7 +238,7 @@ module RangeAnalysis {
225238
/**
226239
* Holds if the given comparison can be modelled as `A <op> B + bias` where `<op>` is the comparison operator.
227240
*/
228-
predicate linearComparison(Comparison comparison, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, int bias) {
241+
predicate linearComparison(Comparison comparison, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, Bias bias) {
229242
exists(Expr left, Expr right, int bias1, int bias2 | left = comparison.getLeftOperand() and right = comparison.getRightOperand() |
230243
// A <= B + c
231244
linearDefinition(left.flow(), a, asign, bias1) and
@@ -247,7 +260,7 @@ module RangeAnalysis {
247260
/**
248261
* Holds if `guard` asserts that the outcome of `A <op> B + bias` is true, where `<op>` is a comparison operator.
249262
*/
250-
predicate linearComparisonGuard(ConditionGuardNode guard, DataFlow::Node a, int asign, string operator, DataFlow::Node b, int bsign, int bias) {
263+
predicate linearComparisonGuard(ConditionGuardNode guard, DataFlow::Node a, int asign, string operator, DataFlow::Node b, int bsign, Bias bias) {
251264
exists (Comparison compare | compare = getDefinition(guard.getTest().flow()).asExpr() |
252265
linearComparison(compare, a, asign, b, bsign, bias) and
253266
(
@@ -279,7 +292,7 @@ module RangeAnalysis {
279292
*
280293
* The dual constraint `-B <= -A + c` is not included in this predicate.
281294
*/
282-
predicate comparisonEdge(ControlFlowNode cfg, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, int bias, boolean sharp) {
295+
predicate comparisonEdge(ControlFlowNode cfg, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, Bias bias, boolean sharp) {
283296
// A <= B + c
284297
linearComparisonGuard(cfg, a, asign, "<=", b, bsign, bias) and
285298
sharp = false
@@ -321,14 +334,14 @@ module RangeAnalysis {
321334
/**
322335
* Holds if `A <= B + c` can be determined based on a phi node.
323336
*/
324-
predicate phiEdge(ControlFlowNode cfg, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, int c) {
337+
predicate phiEdge(ControlFlowNode cfg, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, Bias c) {
325338
exists (DataFlow::Node phi, DataFlow::Node left, DataFlow::Node right |
326339
binaryPhiNode(phi, left, right) and
327340
cfg = phi.getBasicBlock()
328341
|
329342
// Both inputs are defined in terms of the same root:
330343
// phi = PHI(root + bias1, root + bias2)
331-
exists (DataFlow::Node root, int sign, int bias1, int bias2 |
344+
exists (DataFlow::Node root, int sign, Bias bias1, Bias bias2 |
332345
linearDefinition(left, root, sign, bias1) and
333346
linearDefinition(right, root, sign, bias2) and
334347
bias1 < bias2 and
@@ -348,7 +361,7 @@ module RangeAnalysis {
348361
or
349362
// One input is defined in terms of the phi node itself:
350363
// phi = PHI(phi + increment, x)
351-
exists (int increment, DataFlow::Node root, int sign, int bias |
364+
exists (int increment, DataFlow::Node root, int sign, Bias bias |
352365
linearDefinition(left, phi, 1, increment) and
353366
linearDefinition(right, root, sign, bias) and
354367
(
@@ -378,8 +391,9 @@ module RangeAnalysis {
378391
* A + A <= 2c becomes A <= -A + 2c
379392
* A + A >= 2c becomes -A <= A - 2c
380393
*/
381-
predicate constantEdge(ControlFlowNode cfg, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, int c) {
394+
predicate constantEdge(ControlFlowNode cfg, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, Bias c) {
382395
exists (NumberLiteral literal | cfg = literal |
396+
literal.getIntValue() instanceof Bias and // avoid overflow
383397
a = literal.flow() and
384398
b = a and
385399
(asign = 1 or asign = -1) and
@@ -390,7 +404,7 @@ module RangeAnalysis {
390404
/**
391405
* The set of initial edges including those from dual constraints.
392406
*/
393-
private predicate seedEdge(ControlFlowNode cfg, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, int c, boolean sharp) {
407+
predicate seedEdge(ControlFlowNode cfg, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, Bias c, boolean sharp) {
394408
// A <= B + c
395409
comparisonEdge(cfg, a, asign, b, bsign, c, sharp)
396410
or
@@ -399,7 +413,7 @@ module RangeAnalysis {
399413
constantEdge(cfg, a, asign, b, bsign, c) and sharp = false
400414
}
401415

402-
private predicate seedEdgeWithDual(ControlFlowNode cfg, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, int c, boolean sharp) {
416+
private predicate seedEdgeWithDual(ControlFlowNode cfg, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, Bias c, boolean sharp) {
403417
// A <= B + c
404418
seedEdge(cfg, a, asign, b, bsign, c, sharp)
405419
or
@@ -452,10 +466,10 @@ module RangeAnalysis {
452466
*
453467
* This means negative-weight cycles (contradictions) can be detected using simple cycle detection.
454468
*/
455-
private predicate extendedEdge(ControlFlowNode cfg, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, int c, boolean sharp) {
469+
private predicate extendedEdge(ControlFlowNode cfg, DataFlow::Node a, int asign, DataFlow::Node b, int bsign, Bias c, boolean sharp) {
456470
seedEdgeWithDual(cfg, a, asign, b, bsign, c, sharp)
457471
or
458-
exists (DataFlow::Node mid, int midx, ControlFlowNode cfg1, int c1, ControlFlowNode cfg2, int c2, boolean sharp1, boolean sharp2 |
472+
exists (DataFlow::Node mid, int midx, ControlFlowNode cfg1, Bias c1, ControlFlowNode cfg2, Bias c2, boolean sharp1, boolean sharp2 |
459473
extendedEdge(cfg1, a, asign, mid, midx, c1, sharp1) and
460474
extendedEdge(cfg2, mid, midx, b, bsign, c2, sharp2) and
461475
sharp = sharp1.booleanOr(sharp2) and

0 commit comments

Comments
 (0)