Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: changed to comply with DCL02 & DCL04, fixed code, comments and write up to match, fixed typo in intro text

...

This noncompliant code example may result in a signed integer overflow during the addition of the signed operands si1 and si2 si_a and si_b. If this behavior is unanticipated, it can lead to an exploitable vulnerability.

Code Block
bgColor#FFcccc
langc
int si1, si2,si_a;
int si_b;
int sum;

/* Initialize si1si_a and si2si_b */

sum = si1si_a + si2si_b;

Compliant Solution (Precondition Test, Two's Complement)

...

Code Block
bgColor#ccccff
langc
signed int si_a;
signed int si1, si2,si_b;
signed int sum;

/* Initialize si1si_a and si2si_b */

if ( ((si1^si2si_a^si_b) | (((si1^si_a^(~(si1^si2(si_a^si_b) & INT_MIN)) + si2)^si2si_b)^si_b)) >= 0) {
   /* Handle error condition */
} else {
  sum = si1si_a + si2si_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
signed int si_a;
signed int si1, si2,si_b;
signed int sum;

/* Initialize si1si_a and si2si_b */

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

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

...

This noncompliant code example can result in a signed integer overflow during the subtraction of the signed operands si1 and si2 si_a and si_b. If this behavior is unanticipated, the resulting value may be used to allocate insufficient memory for a subsequent operation or in some other manner that can lead to an exploitable vulnerability.

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

/* Initialize si1si_a and si2si_b */

result = si1si_a - si2si_b;

Compliant Solution (Two's Complement)

...

Code Block
bgColor#ccccff
langc
signed int si1, si2,si_a;
signed int si_b;
signed int result;

/* Initialize si1si_a and si2si_b */

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

This compliant solution only works 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
signed int si_a;
signed int si1, si2,si_b;
singed int result;

/* Initialize si1si_a and si2si_b */

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

Anchor
Multiplication
Multiplication

...

This noncompliant code example can result in a signed integer overflow during the multiplication of the signed operands si1 and si2 si_a and si_b. If this behavior is unanticipated, the resulting value may be used to allocate insufficient memory for a subsequent operation or in some other manner that can lead to an exploitable vulnerability.

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

/* ... */

result = si1si_a * si2si_b;

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
signed int si_a;
signed int si1, si2,si_b;
signed int result;

/* Initialize si1si_a and si2si_b */

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

signed long long tmp = (signed long long)si1si_a *
                       (signed long long)si2si_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;
}

...

Code Block
bgColor#ccccff
langc
signed int si_a;
signed int si1, si2,si_b;
signed int result;

/* Initialize si1si_a and si2si_b */

if (si1si_a > 0){  /* si1si_a is positive */
  if (si2si_b > 0) {  /* si1si_a and si2si_b are positive */
    if (si1si_a > (INT_MAX / si2si_b)) {
      /* Handle error condition */
    }
  } /* end if si1si_a and si2si_b are positive */
  else { /* si1si_a positive, si2si_b non-positive */
    if (si2si_b < (INT_MIN / si1si_a)) {
        /* Handle error condition */
    }
  } /* si1si_a positive, si2si_b non-positive */
} /* end if si1si_a is positive */
else { /* si1si_a is non-positive */
  if (si2si_b > 0) { /* si1si_a is non-positive, si2si_b is positive */
    if (si1si_a < (INT_MIN / si2si_b)) {
      /* Handle error condition */
    }
  } /* end if si1si_a is non-positive, si2si_b is positive */
  else { /* si1si_a and si2si_b are non-positive */
    if ( (si1si_a != 0) && (si2si_b < (INT_MAX / si1si_a))) {
      /* Handle error condition */
    }
  } /* end if si1si_a and si2si_b are non-positive */
} /* end if si1si_a is non-positive */

result = si1si_a * si2si_b;

Anchor
Division
Division

Division

...

This noncompliant code example can result in a signed integer overflow during the division of the signed operands sl1 and sl2 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
signed long sl1, sl2,s_a;
signed long s_b;
signed long result;

/* Initialize sl1s_a and sl2s_b */

result = sl1s_a / sl2s_b;

Compliant Solution

This compliant solution guarantees there is no possibility of signed overflow or divide-by-zero errors:

Code Block
bgColor#ccccff
langc
signed long sl1, sl2,s_a;
signed long s_b;
signed long result;

/* Initialize sl1s_a and sl2s_b */

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

Anchor
Modulo
Modulo

Modulo

...

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

result = sl1s_a % sl2s_b;

Implementation Details

On x86 platforms, the modulo operator for signed integers 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.

...

Code Block
bgColor#ccccff
langc
signed long sl1, sl2,s_a;
signed long s_b;
signed long result;

/* Initialize sl1s_a and sl2s_b */

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

Compliant Solution (Absolute Value)

...

Code Block
bgColor#ccccff
langc
signed long sl1, sl2,s_a;
signed long s_b;
signed long result;

/* Initialize sl1s_a and sl2s_b */

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

Anchor
Unary Negation
Unary Negation

...

This noncompliant code example can result in a signed integer overflow during the unary negation of the signed operand si1 s_a:

Code Block
bgColor#FFcccc
langc
signed int si1, long s_a;
signed long result;

/* Initialize si1s_a */

result = -si1s_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
signed int si1, long s_a;
signed long result;

/* Initialize si1s_a */

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

Anchor
Left Shift Operator
Left Shift Operator

...

Code Block
bgColor#FFcccc
langc
int si1, si2,si_a;
int si_b;
int sresult;

/* Initialize si1si_a and si2si_b */

sresult = si1si_a << si2si_b;

Compliant Solution

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

Code Block
bgColor#ccccff
langc
int si1, si2,si_a;
int si_b;
int sresult;

/* Initialize si1si_a and si2si_b */

if ( (si1si_a < 0) || (si2si_b < 0) ||
     (si2si_b >= sizeof(int)*CHAR_BIT) ||
     (si1si_a > (INT_MAX >> si2si_b))
) {
  /* Handle error condition */
}
else {
  sresult = si1si_a << si2si_b;
}

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
atomic_int i;
int si1si_a;

/* Initialize i, si1si_a */

atomic_fetch_add(&i, si1si_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
atomic_int i;
int si1si_a;

/* Initialize si1si_a, i */

int si2si_b = atomic_load(&i);

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

Risk Assessment

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

...