Skip to content

Commit bf37105

Browse files
committed
IntegerOverflow: Support divide and remainder
1 parent 697e2e2 commit bf37105

File tree

4 files changed

+51
-4
lines changed

4 files changed

+51
-4
lines changed

c/cert/src/rules/INT32-C/SignedIntegerOverflow.ql

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,23 @@ import semmle.code.cpp.valuenumbering.GlobalValueNumbering
2121
from InterestingOverflowingOperation op
2222
where
2323
not isExcluded(op, IntegerOverflowPackage::signedIntegerOverflowQuery()) and
24-
op.getType().getUnderlyingType().(IntegralType).isSigned() and
24+
(
25+
// An operation that returns a signed integer type
26+
op.getType().getUnderlyingType().(IntegralType).isSigned()
27+
or
28+
// The divide or rem expression on a signed integer
29+
(op instanceof DivExpr or op instanceof RemExpr) and
30+
op.(BinaryOperation).getLeftOperand().getType().getUnderlyingType().(IntegralType).isSigned()
31+
or
32+
// The assign divide or rem expression on a signed integer
33+
(op instanceof AssignDivExpr or op instanceof AssignRemExpr) and
34+
op.(AssignArithmeticOperation)
35+
.getLValue()
36+
.getType()
37+
.getUnderlyingType()
38+
.(IntegralType)
39+
.isSigned()
40+
) and
2541
// Not checked before the operation
2642
not op.hasValidPreCheck() and
2743
// Not guarded by a check, where the check is not an invalid overflow check

c/cert/test/rules/INT32-C/SignedIntegerOverflow.expected

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
| test.c:62:3:62:10 | ... -= ... | Operation -= of type signed int may overflow or underflow. |
1212
| test.c:69:3:69:8 | ... * ... | Operation * of type int may overflow or underflow. |
1313
| test.c:70:3:70:10 | ... *= ... | Operation *= of type signed int may overflow or underflow. |
14-
| test.c:153:3:153:10 | ... << ... | Operation << of type signed int may overflow or underflow. |
15-
| test.c:154:3:154:11 | ... <<= ... | Operation <<= of type signed int may overflow or underflow. |
16-
| test.c:173:3:173:5 | - ... | Operation - of type signed int may overflow or underflow. |
14+
| test.c:117:3:117:9 | ... / ... | Operation / of type int may overflow or underflow. |
15+
| test.c:118:3:118:10 | ... /= ... | Operation /= of type signed int may overflow or underflow. |
16+
| test.c:140:3:140:9 | ... % ... | Operation % of type int may overflow or underflow. |
17+
| test.c:141:3:141:10 | ... %= ... | Operation %= of type signed int may overflow or underflow. |
18+
| test.c:163:3:163:10 | ... << ... | Operation << of type signed int may overflow or underflow. |
19+
| test.c:164:3:164:11 | ... <<= ... | Operation <<= of type signed int may overflow or underflow. |
20+
| test.c:183:3:183:5 | - ... | Operation - of type signed int may overflow or underflow. |

c/cert/test/rules/INT32-C/test.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ void test_mul_precheck_2(signed int i1, signed int i2) {
114114
}
115115

116116
void test_simple_div(signed int i1, signed int i2) {
117+
i1 / i2; // NON_COMPLIANT
118+
i1 /= i2; // NON_COMPLIANT
119+
}
120+
121+
void test_simple_div_no_zero(signed int i1, signed int i2) {
117122
if (i2 == 0) {
118123
// handle error
119124
} else {
@@ -132,6 +137,11 @@ void test_div_precheck(signed int i1, signed int i2) {
132137
}
133138

134139
void test_simple_rem(signed int i1, signed int i2) {
140+
i1 % i2; // NON_COMPLIANT
141+
i1 %= i2; // NON_COMPLIANT
142+
}
143+
144+
void test_simple_rem_no_zero(signed int i1, signed int i2) {
135145
if (i2 == 0) {
136146
// handle error
137147
} else {

cpp/common/src/codingstandards/cpp/Overflow.qll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,23 @@ class InterestingOverflowingOperation extends Operation {
1919
exprMightOverflowNegatively(this)
2020
or
2121
exprMightOverflowPositively(this)
22+
or
23+
// Division and remainder are not handled by the library
24+
exists(Expr leftOperand, Expr rightOperand |
25+
(this instanceof DivExpr or this instanceof RemExpr) and
26+
leftOperand = this.(BinaryOperation).getLeftOperand() and
27+
rightOperand = this.(BinaryOperation).getRightOperand()
28+
or
29+
(this instanceof AssignDivExpr or this instanceof AssignRemExpr) and
30+
leftOperand = this.(AssignArithmeticOperation).getLValue() and
31+
rightOperand = this.(AssignArithmeticOperation).getRValue()
32+
|
33+
// The right hand side could be -1
34+
upperBound(rightOperand) >= -1.0 and
35+
lowerBound(rightOperand) <= -1.0 and
36+
// The left hand side could be the smallest possible integer value
37+
lowerBound(leftOperand) <= typeLowerBound(leftOperand.getType().getUnderlyingType())
38+
)
2239
) and
2340
// Multiplication is not covered by the standard range analysis library, so implement our own
2441
// mini analysis.

0 commit comments

Comments
 (0)