Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: xferred division & modulo examples from INT32-C to INT33-C

...

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

...


Anchor
Modulo
Modulo

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

...

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

...