Skip to content

Commit fe72b55

Browse files
committed
C++: Range analysis for unsigned AssignMulExpr
This is essentially a copy-paste job of `AssignAddExpr`, together with the math from the `UnsignedMulExpr` support.
1 parent f90d779 commit fe72b55

File tree

4 files changed

+80
-0
lines changed

4 files changed

+80
-0
lines changed

cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ private class UnsignedMulExpr extends MulExpr {
160160
UnsignedMulExpr() { this.getType().(IntegralType).isUnsigned() }
161161
}
162162

163+
private class UnsignedAssignMulExpr extends AssignMulExpr {
164+
UnsignedAssignMulExpr() { this.getType().(IntegralType).isUnsigned() }
165+
}
166+
163167
/** Set of expressions which we know how to analyze. */
164168
private predicate analyzableExpr(Expr e) {
165169
// The type of the expression must be arithmetic. We reuse the logic in
@@ -190,6 +194,8 @@ private predicate analyzableExpr(Expr e) {
190194
or
191195
e instanceof AssignSubExpr
192196
or
197+
e instanceof UnsignedAssignMulExpr
198+
or
193199
e instanceof CrementOperation
194200
or
195201
e instanceof RemExpr
@@ -249,6 +255,14 @@ private predicate defDependsOnDef(
249255
exprDependsOnDef(assignSub.getRValue(), srcDef, srcVar)
250256
)
251257
or
258+
exists(UnsignedAssignMulExpr assignMul, RangeSsaDefinition nextDef |
259+
def = assignMul and
260+
assignMul.getLValue() = nextDef.getAUse(v)
261+
|
262+
defDependsOnDef(nextDef, v, srcDef, srcVar) or
263+
exprDependsOnDef(assignMul.getRValue(), srcDef, srcVar)
264+
)
265+
or
252266
exists(CrementOperation crem |
253267
def = crem and
254268
crem.getOperand() = v.getAnAccess() and
@@ -298,6 +312,10 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria
298312
exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar)
299313
)
300314
or
315+
exists(UnsignedAssignMulExpr mulExpr | e = mulExpr |
316+
exprDependsOnDef(mulExpr.getAnOperand(), srcDef, srcVar)
317+
)
318+
or
301319
exists(CrementOperation crementExpr | e = crementExpr |
302320
exprDependsOnDef(crementExpr.getOperand(), srcDef, srcVar)
303321
)
@@ -669,6 +687,13 @@ private float getLowerBoundsImpl(Expr expr) {
669687
result = addRoundingDown(xLow, -yHigh)
670688
)
671689
or
690+
exists(UnsignedAssignMulExpr mulExpr, float xLow, float yLow |
691+
expr = mulExpr and
692+
xLow = getFullyConvertedLowerBounds(mulExpr.getLValue()) and
693+
yLow = getFullyConvertedLowerBounds(mulExpr.getRValue()) and
694+
result = xLow * yLow
695+
)
696+
or
672697
exists(PrefixIncrExpr incrExpr, float xLow |
673698
expr = incrExpr and
674699
xLow = getFullyConvertedLowerBounds(incrExpr.getOperand()) and
@@ -845,6 +870,13 @@ private float getUpperBoundsImpl(Expr expr) {
845870
result = addRoundingUp(xHigh, -yLow)
846871
)
847872
or
873+
exists(UnsignedAssignMulExpr mulExpr, float xHigh, float yHigh |
874+
expr = mulExpr and
875+
xHigh = getFullyConvertedUpperBounds(mulExpr.getLValue()) and
876+
yHigh = getFullyConvertedUpperBounds(mulExpr.getRValue()) and
877+
result = xHigh * yHigh
878+
)
879+
or
848880
exists(PrefixIncrExpr incrExpr, float xHigh |
849881
expr = incrExpr and
850882
xHigh = getFullyConvertedUpperBounds(incrExpr.getOperand()) and
@@ -1073,6 +1105,14 @@ private float getDefLowerBoundsImpl(RangeSsaDefinition def, StackVariable v) {
10731105
result = addRoundingDown(lhsLB, -rhsUB)
10741106
)
10751107
or
1108+
exists(UnsignedAssignMulExpr assignMul, RangeSsaDefinition nextDef, float lhsLB, float rhsLB |
1109+
def = assignMul and
1110+
assignMul.getLValue() = nextDef.getAUse(v) and
1111+
lhsLB = getDefLowerBounds(nextDef, v) and
1112+
rhsLB = getFullyConvertedLowerBounds(assignMul.getRValue()) and
1113+
result = lhsLB * rhsLB
1114+
)
1115+
or
10761116
exists(IncrementOperation incr, float newLB |
10771117
def = incr and
10781118
incr.getOperand() = v.getAnAccess() and
@@ -1115,6 +1155,14 @@ private float getDefUpperBoundsImpl(RangeSsaDefinition def, StackVariable v) {
11151155
result = addRoundingUp(lhsUB, -rhsLB)
11161156
)
11171157
or
1158+
exists(UnsignedAssignMulExpr assignMul, RangeSsaDefinition nextDef, float lhsUB, float rhsUB |
1159+
def = assignMul and
1160+
assignMul.getLValue() = nextDef.getAUse(v) and
1161+
lhsUB = getDefUpperBounds(nextDef, v) and
1162+
rhsUB = getFullyConvertedUpperBounds(assignMul.getRValue()) and
1163+
result = lhsUB * rhsUB
1164+
)
1165+
or
11181166
exists(IncrementOperation incr, float newUB |
11191167
def = incr and
11201168
incr.getOperand() = v.getAnAccess() and

cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,15 @@
501501
| test.c:488:28:488:29 | ul | 10 |
502502
| test.c:488:33:488:34 | ul | 10 |
503503
| test.c:489:12:489:17 | result | 0 |
504+
| test.c:495:7:495:8 | ui | 0 |
505+
| test.c:495:19:495:20 | ui | 0 |
506+
| test.c:496:5:496:6 | ui | 2 |
507+
| test.c:496:11:496:12 | ui | 2 |
508+
| test.c:497:12:497:13 | ui | 4 |
509+
| test.c:501:3:501:9 | uiconst | 10 |
510+
| test.c:504:3:504:9 | ulconst | 10 |
511+
| test.c:505:10:505:16 | uiconst | 40 |
512+
| test.c:505:20:505:26 | ulconst | 40 |
504513
| test.cpp:10:7:10:7 | b | -2147483648 |
505514
| test.cpp:11:5:11:5 | x | -2147483648 |
506515
| test.cpp:13:10:13:10 | x | -2147483648 |

cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,3 +490,17 @@ unsigned long mult_lower_bound(unsigned int ui, unsigned long ul) {
490490
}
491491
return 0;
492492
}
493+
494+
unsigned long mul_assign(unsigned int ui) {
495+
if (ui <= 10 && ui >= 2) {
496+
ui *= ui + 0;
497+
return ui; // 4 .. 100
498+
}
499+
500+
unsigned int uiconst = 10;
501+
uiconst *= 4;
502+
503+
unsigned long ulconst = 10;
504+
ulconst *= 4;
505+
return uiconst + ulconst; // 40 .. 40 for both
506+
}

cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,15 @@
501501
| test.c:488:28:488:29 | ul | 18446744073709552000 |
502502
| test.c:488:33:488:34 | ul | 18446744073709552000 |
503503
| test.c:489:12:489:17 | result | 18446744073709552000 |
504+
| test.c:495:7:495:8 | ui | 4294967295 |
505+
| test.c:495:19:495:20 | ui | 10 |
506+
| test.c:496:5:496:6 | ui | 10 |
507+
| test.c:496:11:496:12 | ui | 10 |
508+
| test.c:497:12:497:13 | ui | 100 |
509+
| test.c:501:3:501:9 | uiconst | 10 |
510+
| test.c:504:3:504:9 | ulconst | 10 |
511+
| test.c:505:10:505:16 | uiconst | 40 |
512+
| test.c:505:20:505:26 | ulconst | 40 |
504513
| test.cpp:10:7:10:7 | b | 2147483647 |
505514
| test.cpp:11:5:11:5 | x | 2147483647 |
506515
| test.cpp:13:10:13:10 | x | 2147483647 |

0 commit comments

Comments
 (0)