Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: changes to examples to match new coding guidelines

...

Code Block
bgColor#FFcccc
langc
int si_a;
int si_b;
int sum;

void func(void) {
  /* Initialize si_a and si_b */

  sum = si_a + si_b;

  /* ... */
}

Compliant Solution (Precondition Test, Two's Complement)

...

Code Block
bgColor#ccccff
langc
#include <limits.h>
 
signed int si_a;
signed int si_b;
signed int sum;

void func(void) {
  /* Initialize si_a, and si_b and sum*/

  if ( ((si_a^si_b) | (((si_a^(~(si_a^si_b) & INT_MIN)) + si_b)^si_b)) >= 0) {
    /* Handle error condition */
  } else {
    sum = si_a + si_b;
  }

}

This compliant solution works only on architectures that use two's complement representation. Although most modern platforms use two's complement representation, it is best not to introduce unnecessary platform dependencies. (See MSC14-C. Do not introduce unnecessary platform dependencies.) This solution can also be more expensive than a postcondition test, especially on RISC CPUs.

...

Code Block
bgColor#ccccff
langc
#include <limits.h>
 
signed int si_a;
signed int si_b;
signed int sum;

/* Initializevoid (func) {
  /* Initialize si_a, and si_b and sum */

  if (((si_b>0b > 0) && (si_a > (INT_MAX - si_b)))
    || ((si_b<0b < 0) && (si_a < (INT_MIN - si_b)))) {
    /* Handle error condition */
  }
 else {
    sum = si_a + si_b;
  }

}

This solution is more readable but may be less efficient than the solution that is specific to two's complement representation.

...

Code Block
bgColor#FFcccc
langc
signed int si_a;
signed int si_b;
signed int result;

void func(void) {
  /* Initialize si_a and si_b */

  result = si_a - si_b;

  /* ... */
}

Compliant Solution (Two's Complement)

...

Code Block
bgColor#ccccff
langc
#include <limits.h>
 
signed int si_a;
signed int si_b;
signed int result;

void func(void) {
  /* Initialize si_a, and si_b and result */

  if (((si_a^si_b)
    & (((si_a ^ ((si_a^si_b)
    & (1 << (sizeof(int)  *CHAR_BIT -1)))) - si_b)^si_b)) < 0) {
    /* Handle error condition */
  }
 else {
    result = si_a - si_b;
  }

  /* ... */
}

This compliant solution works only on architectures that use two's complement representation. Although most modern platforms use two's complement representation, it is best not to introduce unnecessary platform dependencies. (See MSC14-C. Do not introduce unnecessary platform dependencies.)

...

Code Block
bgColor#ccccff
langc
#include <limits.h>
 
signed int si_a;
signed int si_b;
singed int result;

/* Initialize si_a andvoid func(void) {
  /* Initialize si_a, si_b and result */

  if ((si_b > 0 && si_a < INT_MIN + si_b) ||
    (si_b < 0 && si_a > INT_MAX + si_b)) {
    /* Handle error condition */
  }
 else {
    result = si_a - si_b;
  }

  /* ... */
}

Anchor
Multiplication
Multiplication

...

Code Block
bgColor#FFcccc
langc
signed int si_a;
signed int si_b;
signed int result;

void func(void) {
  /* ... Initialize si_a and si_b */

  result = si_a * si_b;

Compliant Solution


  /* ... */
}

Compliant Solution

This compliant solution guarantees there is no possibility of signed overflow on systems where long long is at least twice the size of int:

Code Block
bgColor#ccccff
langc
#include <assert.h>
 
signed int si_a;
signed int si_b;
signed int result;

void func(void) {
  /* Initialize si_a, and si_b and result */

  static_assert(
    sizeof(long long) >= 2 * sizeof(int),
    "Unable to detect overflow after multiplication"
  );

  signed long long tmp = (signed long long)si_a *
                         (signed long long)si_b;
  /*
   * If the product cannot be represented as a 32-bit integer,
   * handle as an error condition.
   */
  if ( (tmp > INT_MAX) || (tmp < INT_MIN) ) {
    /* Handle error condition */
  }
 else {
    result = (int)tmp;
  }

}

The compliant solution uses a static assertion to ensure that the overflow detection will succeed. See DCL03-C. Use a static assertion to test the value of a constant expression for a discussion of static assertions.

...

Code Block
bgColor#ccccff
langc
signed int #include <limits.h>
 
signed int si_a;
signed int si_b;
signed int result;

void func(void) {
  /* Initialize si_a, and si_b and result */

  if (si_a > 0){  /* si_a is positive */
    if (si_b > 0) {  /* si_a and si_b are positive */
      if (si_a > (INT_MAX / si_b)) {
        /* Handle error condition */
    }
  }
 /* End if si_a and si_b are positive */
   } else { /* si_a positive, si_b nonpositive */
      if (si_b < (INT_MIN / si_a)) {
        /* Handle error condition */
      }
    } /* si_a positive, si_b nonpositive */
  } else { /* End if si_a is positivenonpositive */
else { /* si_a is nonpositive */
  if (si_b > 0) { /* si_a is nonpositive, si_b is positive */
      if (si_a < (INT_MIN / si_b)) {
        /* Handle error condition */
    }
  }
 /* End if si_a is nonpositive, si_b is positive */
  } else { /* si_a and si_b are nonpositive */
      if ( (si_a != 0) && (si_b < (INT_MAX / si_a))) {
        /* Handle error condition */
      }
    } /* End if si_a and si_b are nonpositive */
  } /* End if si_a is nonpositive */

  result = si_a * si_b;

}

Anchor
Division
Division

Division

...

Code Block
bgColor#FFcccc
langc
signed long s_a;
signed long s_b;
signed long result;

void func(void) {
  /* Initialize s_a and s_b */

result  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>
 
signed long s_a;
signed long s_b;
signed long result;

void func(void) {
  /* Initialize s_a and, s_b and result */

  if ( (s_b == 0) || ( (s_a == LONG_MIN) && (s_b == -1) ) ) {
    /* Handle error condition */
  }
 else {
    result = s_a / s_b;
  }

  /* ... */
}

Anchor
Modulo
Modulo

Modulo

The modulo operator provides the remainder when two operands of integer type are divided.

...

Code Block
bgColor#FFcccc
langc
signed long s_a;
signed long s_b;
signed long result;

result = void func(void) {
  /* initialize s_a and s_b */
  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 INT_MIN / -1 overflows, this code will throw a floating-point exception on INT_MIN % -1.

...

Code Block
bgColor#ccccff
langc
#include <limits.h>
 
signed long s_a;
signed long s_b;
signed long result;

void func(void) {
  /* Initialize s_a and, s_b and result */

  if ( (s_b == 0 ) || ( (s_a == LONG_MIN) && (s_b == -1) ) ) {
    /* Handle error condition */
  }
 else {
   result = s_a % s_b;
  }

  /* ... */
}

Compliant Solution (Absolute Value)

...

Code Block
bgColor#ccccff
langc
#include <limits.h>
 
signed long s_a;
signed long s_b;
signed long result;

void func(void) {
  /* Initialize s_a, and s_b and result */

  if (s_b == 0) {
    /* Handle error condition */
  }
 else {
    if ((s_b < 0) && (s_b != LONG_MIN)) {
      s_b = -s_b;
    }
  result = s_a % s_b;
  }

  /* ... */
}

Anchor
Unary Negation
Unary Negation

...

Code Block
bgColor#FFcccc
langc
signed long s_a;
signed long result;

void func(void) {
  /* Initialize s_a */

  result = -s_a;

  /* ... */
}

Compliant Solution

This compliant solution tests the suspect negation operation to guarantee there is no possibility of signed overflow:

Code Block
bgColor#ccccff
langc
#include <limits.h>
 
signed long s_a;
signed long result;

void func(void) {
  /* Initialize s_a and result*/

  if (s_a == INT_MIN) {
    /* Handle error condition */
  }
 else {
    result = -s_a;
  }
}

Anchor
Left Shift Operator
Left Shift Operator

...

Code Block
bgColor#FFcccc
langc
int si_a;
int si_b;
int sresult;

/* Initialize si_a and si_b */

sresult = si_a << si_b;

Compliant Solution

This compliant solution eliminates the possibility of overflow resulting from a left-shift operation:

Code Block
bgColor#ccccff
langc
int si_a;
int si_b;
int sresult;

/* Initialize si_a and si_b */

if ( (si_a < 0) || (si_b < 0) ||
     (si_b >= sizeof(int)*CHAR_BIT) ||
     (si_a > (INT_MAX >> si_b))

void func(void) {
  /* Handle error conditionInitialize si_a and si_b */
}
else {
  sresult = si_a << si_b;

}
  /* ... */
}

Compliant Solution

This compliant solution eliminates the possibility of overflow resulting from a left-shift operation:

This solution is also compliant with INT34-C. Do not shift a negative number of bits or more bits than exist in the operand.

...

Code Block
bgColor#FFcccc
langc
#include <stdatomic.h>
 
atomic_int i;
int si_a;

a;

void func(void) {
  /* Initialize i, si_a */

  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:

Code Block
bgColor#ccccff
langc
#include <limits.h>
#include <stdatomic.h>
 
atomic_int i;
int si_a;

void func(void) {
  /* Initialize si_a, i */

  int si_b = atomic_load(&i);

  if (((si_b>0) && (si_a > (INT_MAX-si_b)))
   || ((si_b<0) && (si_a < (INT_MIN-si_b)))) {
   /* Handle error condition */
  }
 else {
    atomic_fetch_add(&i, si_a);
  }

  /* ... */
}

Risk Assessment

Integer overflow can lead to buffer overflows and the execution of arbitrary code by an attacker.

...