Skip to content

Commit 8cee18b

Browse files
Add assignments to the set of analyzable expressions to simplify overflow detection.
1 parent a3f452b commit 8cee18b

File tree

1 file changed

+68
-11
lines changed

1 file changed

+68
-11
lines changed

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

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ predicate analyzableExpr(Expr e) {
105105
(e instanceof ConditionalExpr) or
106106
(e instanceof AddExpr) or
107107
(e instanceof SubExpr) or
108+
(e instanceof AssignExpr) or
109+
(e instanceof AssignAddExpr) or
110+
(e instanceof AssignSubExpr) or
108111
(e instanceof CrementOperation) or
109112
(e instanceof RemExpr) or
110113
(e instanceof CommaExpr) or
@@ -202,6 +205,18 @@ predicate exprDependsOnDef(
202205
| e = subExpr
203206
| exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar))
204207
or
208+
exists (AssignExpr addExpr
209+
| e = addExpr
210+
| exprDependsOnDef(addExpr.getRValue(), srcDef, srcVar))
211+
or
212+
exists (AssignAddExpr addExpr
213+
| e = addExpr
214+
| exprDependsOnDef(addExpr.getAnOperand(), srcDef, srcVar))
215+
or
216+
exists (AssignSubExpr subExpr
217+
| e = subExpr
218+
| exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar))
219+
or
205220
exists (CrementOperation crementExpr
206221
| e = crementExpr
207222
| exprDependsOnDef(crementExpr.getOperand(), srcDef, srcVar))
@@ -533,6 +548,22 @@ float getLowerBoundsImpl(Expr expr) {
533548
yHigh = getFullyConvertedUpperBounds(subExpr.getRightOperand()) and
534549
result = addRoundingDown(xLow, -yHigh))
535550
or
551+
exists (AssignExpr assign
552+
| expr = assign and
553+
result = getFullyConvertedLowerBounds(assign.getRValue()))
554+
or
555+
exists (AssignAddExpr addExpr, float xLow, float yLow
556+
| expr = addExpr and
557+
xLow = getFullyConvertedLowerBounds(addExpr.getLValue()) and
558+
yLow = getFullyConvertedLowerBounds(addExpr.getRValue()) and
559+
result = addRoundingDown(xLow, yLow))
560+
or
561+
exists (AssignSubExpr subExpr, float xLow, float yHigh
562+
| expr = subExpr and
563+
xLow = getFullyConvertedLowerBounds(subExpr.getLValue()) and
564+
yHigh = getFullyConvertedUpperBounds(subExpr.getRValue()) and
565+
result = addRoundingDown(xLow, -yHigh))
566+
or
536567
exists (PrefixIncrExpr incrExpr, float xLow
537568
| expr = incrExpr and
538569
xLow = getFullyConvertedLowerBounds(incrExpr.getOperand()) and
@@ -655,6 +686,22 @@ float getUpperBoundsImpl(Expr expr) {
655686
yLow = getFullyConvertedLowerBounds(subExpr.getRightOperand()) and
656687
result = addRoundingUp(xHigh, -yLow))
657688
or
689+
exists (AssignExpr assign
690+
| expr = assign and
691+
result = getFullyConvertedUpperBounds(assign.getRValue()))
692+
or
693+
exists (AssignAddExpr addExpr, float xHigh, float yHigh
694+
| expr = addExpr and
695+
xHigh = getFullyConvertedUpperBounds(addExpr.getLValue()) and
696+
yHigh = getFullyConvertedUpperBounds(addExpr.getRValue()) and
697+
result = addRoundingUp(xHigh, yHigh))
698+
or
699+
exists (AssignSubExpr subExpr, float xHigh, float yLow
700+
| expr = subExpr and
701+
xHigh = getFullyConvertedUpperBounds(subExpr.getLValue()) and
702+
yLow = getFullyConvertedLowerBounds(subExpr.getRValue()) and
703+
result = addRoundingUp(xHigh, -yLow))
704+
or
658705
exists (PrefixIncrExpr incrExpr, float xHigh
659706
| expr = incrExpr and
660707
xHigh = getFullyConvertedUpperBounds(incrExpr.getOperand()) and
@@ -1132,7 +1179,7 @@ private cached module SimpleRangeAnalysisCached {
11321179
// single minimum value.
11331180
result = min(float lb | lb = getTruncatedLowerBounds(expr) | lb)
11341181
}
1135-
1182+
11361183
/**
11371184
* Gets the upper bound of the expression.
11381185
*
@@ -1151,7 +1198,7 @@ private cached module SimpleRangeAnalysisCached {
11511198
// single maximum value.
11521199
result = max(float ub | ub = getTruncatedUpperBounds(expr) | ub)
11531200
}
1154-
1201+
11551202
/**
11561203
* Holds if `expr` has a provably empty range. For example:
11571204
*
@@ -1180,13 +1227,13 @@ private cached module SimpleRangeAnalysisCached {
11801227
predicate defMightOverflowNegatively(RangeSsaDefinition def, LocalScopeVariable v) {
11811228
getDefLowerBoundsImpl(def, v) < varMinVal(v)
11821229
}
1183-
1230+
11841231
/** Holds if the definition might overflow positively. */
11851232
cached
11861233
predicate defMightOverflowPositively(RangeSsaDefinition def, LocalScopeVariable v) {
11871234
getDefUpperBoundsImpl(def, v) > varMaxVal(v)
11881235
}
1189-
1236+
11901237
/**
11911238
* Holds if the definition might overflow (either positively or
11921239
* negatively).
@@ -1196,17 +1243,22 @@ private cached module SimpleRangeAnalysisCached {
11961243
defMightOverflowNegatively(def, v) or
11971244
defMightOverflowPositively(def, v)
11981245
}
1199-
1246+
12001247
/**
12011248
* Holds if the expression might overflow negatively. This predicate
12021249
* does not consider the possibility that the expression might overflow
12031250
* due to a conversion.
12041251
*/
12051252
cached
12061253
predicate exprMightOverflowNegatively(Expr expr) {
1207-
getLowerBoundsImpl(expr) < exprMinVal(expr)
1254+
getLowerBoundsImpl(expr) < exprMinVal(expr) or
1255+
1256+
// The lower bound of the expression `x--` is the same as the lower
1257+
// bound of `x`, so the standard logic (above) does not work for
1258+
// detecting whether it might overflow.
1259+
getLowerBoundsImpl(expr.(PostfixDecrExpr)) = exprMinVal(expr)
12081260
}
1209-
1261+
12101262
/**
12111263
* Holds if the expression might overflow negatively. Conversions
12121264
* are also taken into account. For example the expression
@@ -1218,17 +1270,22 @@ private cached module SimpleRangeAnalysisCached {
12181270
exprMightOverflowNegatively(expr) or
12191271
convertedExprMightOverflowNegatively(expr.getConversion())
12201272
}
1221-
1273+
12221274
/**
12231275
* Holds if the expression might overflow positively. This predicate
12241276
* does not consider the possibility that the expression might overflow
12251277
* due to a conversion.
12261278
*/
12271279
cached
12281280
predicate exprMightOverflowPositively(Expr expr) {
1229-
getUpperBoundsImpl(expr) > exprMaxVal(expr)
1281+
getUpperBoundsImpl(expr) > exprMaxVal(expr) or
1282+
1283+
// The upper bound of the expression `x++` is the same as the upper
1284+
// bound of `x`, so the standard logic (above) does not work for
1285+
// detecting whether it might overflow.
1286+
getUpperBoundsImpl(expr.(PostfixIncrExpr)) = exprMaxVal(expr)
12301287
}
1231-
1288+
12321289
/**
12331290
* Holds if the expression might overflow positively. Conversions
12341291
* are also taken into account. For example the expression
@@ -1240,7 +1297,7 @@ private cached module SimpleRangeAnalysisCached {
12401297
exprMightOverflowPositively(expr) or
12411298
convertedExprMightOverflowPositively(expr.getConversion())
12421299
}
1243-
1300+
12441301
/**
12451302
* Holds if the expression might overflow (either positively or
12461303
* negatively). The possibility that the expression might overflow

0 commit comments

Comments
 (0)