Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Minor edits; reviewed

...

Addition is between two operands of arithmetic type or between a pointer to an object type and an integer type. (See ARR37-C. Do not add or subtract an integer to a pointer to a non-array object and ARR38ARR30-C. Do not add or subtract an integer to a pointer if the resulting value does not refer to a valid array elementform or use out of bounds pointers or array subscripts.) Incrementing is equivalent to adding 1.

...

Code Block
bgColor#FFcccc
langc
void func(signed int si_a;
, signed int si_b;
int sum;

void func(void) {
  /* Initialize si_a and si_b */
  signed int sum = si_a + si_b;

  /* ... */
}

...

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

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

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

...

Subtraction is between two operands of arithmetic type, two pointers to qualified or unqualified versions of compatible object types, or a pointer to an object type and an integer type. See ARR36-C. Do not subtract or compare two pointers that do not refer to the same array, ARR37-C. Do not add or subtract an integer to a pointer to a non-array object, and ARR38and ARR30-C. Do not add or subtract an integer to a pointer if the resulting value does not refer to a valid array elementform or use out of bounds pointers or array subscripts for information about pointer subtraction. Decrementing is equivalent to subtracting 1.

...

Code Block
bgColor#FFcccc
langc
signedvoid func(signed int si_a;
, signed int si_b;
signed int result;

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

  result int diff = si_a - si_b;

  /* ... */
}

...

Code Block
bgColor#ccccff
langc
#include <limits.h>
 
void func(signed int si_a;
, signed int si_b;
singed) {
  signed int resultdiff;

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

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

  /* ... */
}

...

Code Block
bgColor#FFcccc
langc
void func(signed int si_a;
, signed int si_b;
signed int result;

void func(void) {
  /* Initialize si_a and si_b */
  signed int result = si_a * si_b;

  /* ... */
}

...

Code Block
bgColor#ccccff
langc
#include <assert.h>
 
void func(signed int si_a;
, signed int si_b;) {
  signed int result;

void func(void) {
  /*signed Initialize si_a, si_b and result */long long tmp;
  assert( UWIDTH( signed long long, ULLONG_MAX) >=
          2 * UWIDTH( int, UINT_MAX));
  signed long long 
  tmp = (signed long long)si_a *
 (signed long long)si_b;
 
  /*
   * If                (signed long long)si_b;
  /*
   * If the 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 assertion fails if long long has less than twice the width of int. It relies on the UWIDTH() macro, which is defined in INT19-C. Correctly compute integer widths.

On systems where this assertion would fail, the following compliant solution may be used to ensure signed overflow does not occur:

Code Block
bgColor#ccccff
langc
#include <limits.h>
 
void func(signed int si_a;
, signed int si_b;) {
  signed int result;

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

  if (si_a > 0) {  /* sisi_a is positive */
    if (si_b > 0) {  /* si_a and si_b are positive */
      if (si_a > (INT_MAX / si_b)) {
        /* Handle error condition */
      }
    } else { /* si_a positive, si_b nonpositive */
      if (si_b < (INT_MIN / si_a)) {
        /* Handle error condition */
      }
    } /* si_a positive, si_b nonpositive */
  } 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 */
      }
    } 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
void func(signed long s_a;
, signed long s_b;) {
  signed long result = s_a / s_b;

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

  /* ... */
}

Compliant Solution

...

Code Block
bgColor#ccccff
langc
#include <limits.h>
 
void func(signed long s_a;
, signed long s_b;) {
  signed long result;

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

  /* ... */
}

...

Code Block
bgColor#FFcccc
langc
void func(signed long s_a;
, signed long s_b;) {
  signed long 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.

On MSVC++Microsoft Visual Studio 2012, taking the modulo of INT_MIN by by −1 yields the value 0. On GCC/Linux, taking the modulo of INT_MIN by by −1 produces a floating-point exception. However, on GCC 4.2.4 and newer, with optimization enabled, taking the modulo of INT_MIN by by −1 yields the value 0.

Compliant Solution (Overflow Prevention)

...

Code Block
bgColor#ccccff
langc
#include <limits.h>
 
void func(signed long s_a;
, signed long s_b;) {
  signed long result;

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

  /* ... */
}

...

Code Block
i % -j

are always equivalent.

FurthermoreHowever, it guarantees that the minimum signed value modulo −1 yields 0:modulo −1 results in undefined behavior because the minimum signed value divided by -1 is not representable.

Code Block
bgColor#ccccff
langc
#include <limits.h>
 
void func(signed long s_a;
, signed long s_b;) {
  signed long result;

void  if func(void) {
  /* Initialize s_b == 0 || (s_a, == sLONG_b and result */

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

  /* ... */
}

...

Code Block
bgColor#FFcccc
langc
void func(signed long s_a;) {
  signed long result = -s_a;

void func(void) {
  /* Initialize s_a */
  result = -s_a;

  /* ... */
}

Compliant Solution

...

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

void func(void) {
  /* Initialize s_a and result */signed long result;
  if (s_a == INT_MIN) {
    /* Handle error condition */
  } else {
    result = -s_a;
  }
  /* ... */
}

...

Code Block
bgColor#FFcccc
langc
intvoid func(signed long si_a;
int, signed long si_b;
int sresult;

void func(void) {
  /*signed Initialize si_a and si_b */
  sresult long result = si_a << si_b;

  /* ... */
}

...

Code Block
bgColor#ccccff
langc
#include <limits.h>

 
void func(signed long ssi_a;
, signed long si_b) {
  signed long result;

void func(void) {
  if ((si1si_a < 0) || (si2si_b < 0) ||
      (si2si_b >= UWIDTH(signed long, ULONG_MAX)) ||
      (si1si_a > (INT_MAX >> si2si_b))) {
    /* Handle error condition */
  } else {
    sresultresult = si1 << si2;
  }

 
  /* ... */
}

Anchor
Left Shift Operator
Left Shift Operator

The UWIDTH() macro provides the correct width for an unsigned integer type, and is defined in INT19-C. Correctly compute integer widths...see that rule for more information. This solution also complies 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;

void func(int si_a;

void func(void) {
  /* Initialize atomic_init(&i, si_a */42); 
  atomic_fetch_add(&i, si_a);

  /* ... */
}

...

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.

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

void func(int si_a;

void func(void) {
  /*int Initialize si_a, i */
  int si_b = atomic_load(&i);

  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 {
    atomic_store(&i, si_a + si_b);
  }

  /* ... */
}

...

Tool

Version

Checker

Description

Coverity6.5TAINTED_STATICFully Implemented

Fortify SCA

5.0

 

Can detect violations of this rule with CERT C Rule Pack. Specifically, it checks to ensure that the operand of a unary negation is compared to the type's minimum value immediately before the operation

LDRA tool suite

Include Page
LDRA_V
LDRA_V

43 D
493 S
494 S

Partially implementedPRQA QA-C
Include Page
PRQA_VPRQA_V

0278
0296
0297
2800

Fully implemented

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

Partially implemented
PRQA QA-C
Include Page
PRQA_V
PRQA_V

0278
0296
0297
2800

Fully implemented

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

...

[Dowd 2006]Chapter 6, "C Language Issues" ("Arithmetic Boundary Conditions," pp. 211–223)
[ISO/IEC 9899:2011]Subclause 6.5.5, "Multiplicative Operators"
[Seacord 2013]Chapter 5, "Integer Security"
[Viega 2005]Section 5.2.7, "Integer Overflow"
[VU#551436] 
[Warren 2002]Chapter 2, "Basics"

 

...