...
This noncompliant code example may result in a signed integer overflow during the addition of the signed operands si1 and si2. If this behavior is unanticipated, it can lead to an exploitable vulnerability.
| Code Block | ||||
|---|---|---|---|---|
| ||||
int si1, si2, sum; /* Initialize si1 and si2 */ sum = si1 + si2; |
...
This compliant solution performs a pre-condition test of the operands of the addition to ensure no overflow occurs, assuming two's complement representation.
| Code Block | ||||
|---|---|---|---|---|
| ||||
signed int si1, si2, sum;
/* Initialize si1 and si2 */
if ( ((si1^si2) | (((si1^(~(si1^si2) & INT_MIN)) + si2)^si2)) >= 0) {
/* handle error condition */
} else {
sum = si1 + si2;
}
|
...
This compliant solution tests the suspect addition operation to ensure no overflow occurs regardless of representation.
| Code Block | ||||
|---|---|---|---|---|
| ||||
signed int si1, si2, sum;
/* Initialize si1 and si2 */
if (((si2>0) && (si1 > (INT_MAX-si2)))
|| ((si2<0) && (si1 < (INT_MIN-si2)))) {
/* handle error condition */
}
else {
sum = si1 + si2;
}
|
...
This noncompliant code example can result in a signed integer overflow during the subtraction of the signed operands si1 and si2. 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, result; /* Initialize si1 and si2 */ result = si1 - si2; |
...
This compliant solution tests the operands of the subtraction to guarantee there is no possibility of signed overflow, presuming two's complement representation.
| Code Block | ||||
|---|---|---|---|---|
| ||||
signed int si1, si2, result;
/* Initialize si1 and si2 */
if (((si1^si2)
& (((si1 ^ ((si1^si2)
& (1 << (sizeof(int)*CHAR_BIT-1))))-si2)^si2)) < 0) {
/* handle error condition */
}
else {
result = si1 - si2;
}
|
...
This compliant solution tests the operands of the subtraction to guarantee there is no possibility of signed overflow, regardless of representation.
| Code Block | ||||
|---|---|---|---|---|
| ||||
signed int si1, si2, result;
/* Initialize si1 and si2 */
if ((si2 > 0 && si1 < INT_MIN + si2) ||
(si2 < 0 && si1 > INT_MAX + si2)) {
/* handle error condition */
}
else {
result = si1 - si2;
}
|
...
This noncompliant code example can result in a signed integer overflow during the multiplication of the signed operands si1 and si2. 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, result; /* ... */ result = si1 * si2; |
...
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 si1, si2, result;
/* Initialize si1 and si2 */
static_assert(
sizeof(long long) >= 2 * sizeof(int),
"Unable to detect overflow after multiplication"
);
signed long long tmp = (signed long long)si1 *
(signed long long)si2;
/*
* 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;
}
|
...
On systems where this relationship does not exist, the following compliant solution may be used to ensure signed overflow does not occur.
| Code Block | ||||
|---|---|---|---|---|
| ||||
signed int si1, si2, result;
/* Initialize si1 and si2 */
if (si1 > 0){ /* si1 is positive */
if (si2 > 0) { /* si1 and si2 are positive */
if (si1 > (INT_MAX / si2)) {
/* handle error condition */
}
} /* end if si1 and si2 are positive */
else { /* si1 positive, si2 non-positive */
if (si2 < (INT_MIN / si1)) {
/* handle error condition */
}
} /* si1 positive, si2 non-positive */
} /* end if si1 is positive */
else { /* si1 is non-positive */
if (si2 > 0) { /* si1 is non-positive, si2 is positive */
if (si1 < (INT_MIN / si2)) {
/* handle error condition */
}
} /* end if si1 is non-positive, si2 is positive */
else { /* si1 and si2 are non-positive */
if ( (si1 != 0) && (si2 < (INT_MAX / si1))) {
/* handle error condition */
}
} /* end if si1 and si2 are non-positive */
} /* end if si1 is non-positive */
result = si1 * si2;
|
...
This noncompliant code example can result in a signed integer overflow during the division of the signed operands sl1 and sl2 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, result; /* Initialize sl1 and sl2 */ result = sl1 / sl2; |
...
This compliant solution guarantees there is no possibility of signed overflow or divide-by-zero errors.
| Code Block | ||||
|---|---|---|---|---|
| ||||
signed long sl1, sl2, result;
/* Initialize sl1 and sl2 */
if ( (sl2 == 0) || ( (sl1 == LONG_MIN) && (sl2 == -1) ) ) {
/* handle error condition */
}
else {
result = sl1 / sl2;
}
|
...
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 in spite of the fact that the result of such a modulo operation should theoretically be 0.
| Code Block | ||||
|---|---|---|---|---|
| ||||
signed long sl1, sl2, result; result = sl1 % sl2; |
...
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 | ||||
|---|---|---|---|---|
| ||||
signed long sl1, sl2, result;
/* Initialize sl1 and sl2 */
if ( (sl2 == 0 ) || ( (sl1 == LONG_MIN) && (sl2 == -1) ) ) {
/* handle error condition */
}
else {
result = sl1 % sl2;
}
|
...
Furthermore, it guarantees that the minumum signed value modulo -1 yields 0.
| Code Block | ||||
|---|---|---|---|---|
| ||||
signed long sl1, sl2, result;
/* Initialize sl1 and sl2 */
if (sl2 == 0) {
/* handle error condition */
}
else {
if ((sl2 < 0) && (sl2 != LONG_MIN)) {
sl2 = -sl2;
}
result = sl1 % sl2;
}
|
...
This noncompliant code example can result in a signed integer overflow during the unary negation of the signed operand si1.
| Code Block | ||||
|---|---|---|---|---|
| ||||
signed int si1, result; /* Initialize si1 */ result = -si1; |
...
This compliant solution tests the suspect negation operation to guarantee there is no possibility of signed overflow.
| Code Block | ||||
|---|---|---|---|---|
| ||||
signed int si1, result;
/* Initialize si1 */
if (si1 == INT_MIN) {
/* handle error condition */
}
else
result = -si1;
}
|
...
This noncompliant code example can result in signed integer overflow.
| Code Block | ||||
|---|---|---|---|---|
| ||||
int si1, si2, sresult; /* Initialize si1 and si2 */ sresult = si1 << si2; |
...
This compliant solution eliminates the possibility of overflow resulting from a left-shift operation.
| Code Block | ||||
|---|---|---|---|---|
| ||||
int si1, si2, sresult;
/* Initialize si1 and si2 */
if ( (si1 < 0) || (si2 < 0) ||
(si2 >= sizeof(int)*CHAR_BIT) ||
(si1 > (INT_MAX >> si2))
) {
/* handle error condition */
}
else {
sresult = si1 << si2;
}
|
...