Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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
bgColor#FFcccc
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
bgColor#ccccff
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
bgColor#ccccff

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
Unary Negation
Unary Negation

...

Code Block
bgColor#FFcccc
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
bgColor#FFcccc
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.

...