Integer operations must result in an integer value within the range of the integer type (that is, the resulting value is the same as the result produced by unlimited-range integers). Frequently the range is more restrictive based on the use of the integer value, for example, as an index. Integer values can be verified by code review or by static analysis.
Verifiably in range operations are often preferable to treating out of range values as an error condition because the handling of these errors has been repeatedly shown to cause denial-of-service problems in actual applications. The quintessential example of this is the failure of the Ariane 5 launcher which occurred due to an improperly handled conversion error resulting in the processor being shutdown [[Lions 96]].
Faced with an integer overflow, the underlying computer system may do one of two things: (a) signal some sort of error condition, or (b) produce an integer result that is within the range of representable integers on that system. The latter semantics may be preferable in some situations in that it allows the computation to proceed, thus avoiding a denial-of-service attack. However, it raises the question of what integer result to return to the user.
The saturation and modwrap algorithms, defined in the following subsections, produce integer results that are always within a defined range. This range is between the integer values MIN
and MAX
(inclusive), where MIN
and MAX
are two representable integers with MIN < MAX
.
Saturation Semantics
For saturation semantics, assume that the mathematical result of the computation is result
. The value actually returned to the user is set out in the following table:
range of mathematical result |
result returned |
---|---|
|
|
|
|
|
|
Modwrap Semantics
In modwrap semantics (also called modulo arithmetic), integer values "wrap round". That is, adding one to MAX
produces MIN
. This is the defined behavior for unsigned integers in the C Standard [[ISO/IEC 9899-1999]] (see Section 6.2.5, "Types", paragraph 9) and is frequently the behavior of signed integers as well. However, it is more sensible in many applications to use saturation semantics instead of modwrap semantics. For example, in the computation of a size (using unsigned integers), it is often better for the size to stay at the maximum value in the event of overflow, rather than suddenly becoming a very small value.
Restricted Range Usage
Another tool for avoiding integer overflow is to use only half the range of signed integers. For example, when using an int
, use only the range [INT_MIN
/2, INT_MAX
/2]. This has been a trick of the trade in Fortran for some time, and now that optimizing C compilers are becoming more sophisticated, it can be valuable in C.
Non-Compliant Code Example
In the following non-compliant example, i + 1
will overflow on a 16-bit machine. The C standard allows signed integers to overflow and produce incorrect results, and compilers can take advantage of this to produce faster code by assuming an overflow will not happen. Therefore, the if
statement that is intended to catch an overflow might be optimized away.
int i = /* some expression that evaluates to the value 32767 */; /* ... */ if (i + 1 < i) { /* handle overflow */ }
Compliant Solution
Using a long
instead of an int
is guaranteed to accommodate the computed value.
long i = /* some expression that evaluates to the value 32767 */; /* ... */ /* No test is necessary; i is known not to overflow. */
Risk Assessment
If an integer overflow produces an unexpected value which is then used to index into an array, a buffer overflow could result.
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
INT08-A |
2 (medium) |
2 (probable) |
1 (high) |
P4 |
L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[Lions 96]]
INT07-A. Use only signed or unsigned char type for numeric values 04. Integers (INT) INT09-A. Ensure enumeration constants map to unique values