...
Division is between two operands of arithmetic type. Overflow can occur during two's complement signed integer division when the dividend is equal to the minimum (negative) value for the signed integer type and the divisor is equal to −1. Division operations are also susceptible to divide-by-zero errors. (See INT33-C. Ensure that division and modulo operations do not result in divide-by-zero errors.)
Noncompliant Code Example
This noncompliant code example can result in a signed integer overflow during the division of the signed operands s_a
and s_b
or in a divide-by-zero error. The IA-32 architecture, for example, requires that both conditions result in a fault, which can easily result in a denial-of-service attack.
Code Block | ||||
---|---|---|---|---|
| ||||
void func(signed long s_a, signed long s_b) {
signed long result = s_a / s_b;
/* ... */
} |
Compliant Solution
This compliant solution guarantees there is no possibility of signed overflow or divide-by-zero errors:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h>
void func(signed long s_a, signed long s_b) {
signed long result;
if ((s_b == 0) || ((s_a == LONG_MIN) && (s_b == -1))) {
/* Handle error */
} else {
result = s_a / s_b;
}
/* ... */
} |
...
Modulo
The modulo operator provides the remainder when two operands of integer type are divided.
Noncompliant Code Example
This noncompliant code example can result in a divide-by-zero error. Furthermore, many hardware platforms implement modulo as part of the division operator, which can overflow. Overflow can occur during a modulo operation when the dividend is equal to the minimum (negative) value for the signed integer type and the divisor is equal to −1. This occurs despite that the result of such a modulo operation should theoretically be 0.
Code Block | ||||
---|---|---|---|---|
| ||||
void func(signed long s_a, signed long s_b) {
signed long result = s_a % s_b;
/* ... */
} |
Implementation Details
On x86 platforms, the modulo operator for signed integers is implemented by the idiv
instruction code, along with the divide operator. Because LONG_MIN / -1
overflows, this code will throw a floating-point exception on LONG_MIN % -1
.
On Microsoft Visual Studio 2013, taking the modulo of LONG_MIN
by −1
results in abnormal termination on x86 and x64. On GCC/Linux, taking the modulo of LONG_MIN
by −1
produces a floating-point exception. However, on GCC 4.2.4 and newer, with optimization enabled, taking the modulo of LONG_MIN
by −1
yields the value 0
.
Compliant Solution (Overflow Prevention)
This compliant solution tests the modulo operand to guarantee there is no possibility of a divide-by-zero error or an (internal) overflow error:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h>
void func(signed long s_a, signed long s_b) {
signed long result;
if ((s_b == 0) || ((s_a == LONG_MIN) && (s_b == -1))) {
/* Handle error */
} else {
result = s_a % s_b;
}
/* ... */
} |
Compliant Solution (Absolute Value)
This compliant solution is based on the fact that both the division and modulo operators truncate toward 0, as specified in subclause 6.5.5, footnote 105, of the C Standard [ISO/IEC 9899:2011], which guarantees that
Code Block |
---|
i % j
|
and
Code Block |
---|
i % -j
|
are always equivalent.
However, the minimum signed value modulo −1
results in undefined behavior because the minimum signed value divided by -1
is not representable.
...
bgColor | #ccccff |
---|---|
lang | c |
...
Anchor | ||||
---|---|---|---|---|
|
Modulo
The modulo operator provides the remainder when two operands of integer type are divided. Because many platforms implement modulo and division in the same instruction, the modulo operator has the same possibilities of arithmetic overflow and division by 0. (See INT33-C. Ensure that division and modulo operations do not result in divide-by-zero errors.)
...
Anchor | ||||
---|---|---|---|---|
|
...
The unary negation operator takes an operand of arithmetic type. Overflow can occur during two's complement unary negation when the operand is equal to the minimum (negative) value for the signed integer type.
Noncompliant Code Example
This noncompliant code example can result in a signed integer overflow during the unary negation of the signed operand s_a
:
Code Block | ||||
---|---|---|---|---|
| ||||
void func(signed long s_a) { signed long result = -s_a; /* ... */ } |
Compliant Solution
This compliant solution tests the suspect negation operation to guarantee there is no possibility of signed overflow:
...
The left-shift operator is between two operands of integer type.
Noncompliant Code Example
This noncompliant code example can result in signed integer overflow:
Code Block | ||||
---|---|---|---|---|
| ||||
void func(signed long si_a, signed long si_b) { signed long result = si_a << si_b; /* ... */ } |
Compliant Solution
This compliant solution eliminates the possibility of overflow resulting from a left-shift operation:
...
This section includes an example for the addition of atomic integer types only. For other operations, tests similar to the precondition tests for two’s complement integers used for nonatomic integer types can be used.
Noncompliant Code Example
This noncompliant code example using atomic integers can result in unexpected signed integer overflow:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdatomic.h> atomic_int i; void func(int si_a) { atomic_init(&i, 42); atomic_fetch_add(&i, si_a); /* ... */ } |
Compliant Solution
This compliant solution tests the operands to guarantee there is no possibility of signed overflow. It loads the value stored in the atomic integer and tests for possible overflow before performing the addition. However, this code contains a race condition where i
can be modified after the load, but prior to the atomic store. This solution is only compliant if i
is guaranteed to only be access by a single thread. See CON43-C. Do not assume that a group of calls to independently atomic methods is atomic for more information.
...