...
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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;
|
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 |
---|
|
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 |
---|
|
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;
}
|
Modulo
...
Code Block |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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.
...