Abstract
Integer range checking, if implemented correctly, can eliminate vulnerabilities resulting from integer overflow, truncation, and sign errors.
Development Context
Integer operations
Technology Context
C, C++, IA-32, Win32, UNIX
Attacks
Attacker executes arbitrary code on machine with permissions of compromised process or changes the behavior of the program.
Risk
Integers in C and C++ are susceptible to overflow, sign, and truncation errors that can lead to exploitable vulnerabilities.
Description
As you may have expected, the burden for integer range checking in C and C++ is placed squarely on the programmer’s shoulders. Sometimes it’s relatively easy, sometimes it’s not. It’s relatively easy, for example, to check an integer value to make sure it is within the proper range before using it to index an array. An out-of range value (for example, a negative integer) can be used to bypass a check on the upper bound of an array and cause a buffer overflow. Figure 1 shows an example that uses both implicit type checking and explicit range checks. The implicit type check results from the declaration, on line 3, of len as an unsigned integer. In general, it is a good idea to use unsigned types for indices, sizes, and loop counters that should never have negative values. The memcpy() call on line 7 is also protected by an explicit range check on line 6 that tests both the upper and lower bounds.
Figure 1. Implementation with implicit type and explicit range checking
1. #define BUFF_SIZE 10 2. int main(int argc, char* argv[]) { 3. unsigned int len; 4. char buf[BUFF_SIZE]; 5. len = atoi(argv[1]); 6. if ((0 < len) && (len < BUFF_SIZE) ) { 7. memcpy(buf, argv[2], len); 8. } 9. else 10. printf("Too much data"); 11. }
Declaring len to be an unsigned integer is insufficient for range restriction because it only restricts the range from 0..MAX_INT. The range check on line 6 is sufficient to ensure that no out-of-range values are passed to memcpy() as long as both the upper and lower bounds are checked. Using both the implicit and explicit checks may be redundant, but we recommend this practice as “healthy paranoia.”
In other cases, type range checking is more complicated. For example, if x is assigned the product of a, b, and c, it is necessary to limit the range of a, b, and c so that the value of x cannot exceed the range of values for whichever integer type x is declared. As integer variables are operated on multiple times in combination with other integer values, it becomes increasingly difficult to ensure that an integer type range error does not occur.
While this problem is difficult to solve, there are valid software engineering techniques that can help. First, all external inputs should be evaluated to determine whether there are identifiable upper and lower bounds. If so, these limits should be enforced by the interface. Anything that can be done to limit the input of excessively large or small integers should help prevent overflow and other type range errors. Furthermore, it is easier to find and correct input problems than it is to trace internal errors back to faulty inputs.
Second, typographic conventions can be used in the code to distinguish constants from variables. They can even be used to distinguish externally influenced variables from locally used variables with well-defined ranges.
Third, strong typing should be used so that the compiler can be more effective in identifying range problems.
Copyright © Carnegie Mellon University 2005-2012.
This material may be reproduced in its entirety, without modification, and freely distributed in written or electronic form without requesting formal permission. Permission is required for any other use. Requests for permission should be directed to the Software Engineering Institute at permission@sei.cmu.edu.
The Build Security In (BSI) portal is sponsored by the U.S. Department of Homeland Security (DHS), National Cyber Security Division. The Software Engineering Institute (SEI) develops and operates BSI. DHS funding supports the publishing of all site content.
NO WARRANTY
THIS MATERIAL OF CARNEGIE MELLON UNIVERSITY AND ITS SOFTWARE ENGINEERING INSTITUTE IS FURNISHED ON AN “AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.