...
This noncompliant code example can result in a divide-by-zero or an overflow error during the modulo operation on the signed operands sl1 and sl2error. 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 in spite of the fact that the result of such a modulo operation should theoretically be 0.
| Code Block | ||
|---|---|---|
| ||
signed long sl1, sl2, result; result = sl1 % sl2; |
Implementation Details
On MSVC++x86 platforms, taking the modulo operator for signed ints is implemented by the idiv instruction code, along with the divide operator. Since INT_MIN / -1 overflows, this code will throw a floating-point exception on INT_MIN % -1.
On MSVC++, taking the modulo of INT_MIN by -1 yields the value 0. of INT_MIN by -1 yields the value 0. On gcc/Linux, taking the modulo of INT_MIN by -1 produces a floating-point exception. However, on gcc versions 4.2.4 and newer, with optimization enabled, taking the modulo of INT_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 | ||
|---|---|---|
| ||
signed long sl1, sl2, result;
/* Initialize sl1 and sl2 */
if ( (sl2 == 0 ) || ( (sl1 == LONG_MIN) && (sl2 == -1) ) ) {
/* handle error condition */
}
else {
result = sl1 % sl2;
}
|
Compliant Solution (Absolute Value)
This compliant solution is based on the fact that both the division and modulo operators truncate towards zero, as specified in a footnote in paragraph 6.5.5 of the C99 standard. This guarantees that:
| Code Block |
|---|
i % j
|
and
| Code Block |
|---|
i % -j
|
are always equivalent.
Furthermore, it guarantees that the minumum signed value modulo -1 yields 0.
| Code Block | ||
|---|---|---|
| ||
signed long sl1, sl2, result;
/* Initialize sl1 and sl2 */
if (sl2 == 0) {
/* handle error condition */
}
else {
if ((sl2 < 0) && (sl2 != LONG_MIN)) {
sl2 = -sl2;
}
result = sl1 % sl2;
}
|
| Anchor | ||||
|---|---|---|---|---|
|
...
| Code Block | ||
|---|---|---|
| ||
signed int si1, result; /* Initialize si1 */ result = -si1; |
Compliant Solution
This compliant solution tests the suspect negation operation to guarantee there is no possibility of signed overflow.
...
| Code Block | ||
|---|---|---|
| ||
int si1, si2, sresult; /* Initialize si1 and si2 */ sresult = si1 << si2; |
Compliant Solution
This compliant solution eliminates the possibility of overflow resulting from a left-shift operation.
...