Do not use functions that input characters and convert them to integers if the functions cannot handle all possible inputs. For example, formatted input functions such as scanf()
, fscanf()
, vscanf()
, and vfscanf()
can be used to read string data from stdin
or (in the cases of fscanf()
and vfscanf()
) other input streams. These functions work fine for valid integer values but lack robust error handling for invalid values.
Alternatively, input character data as a null-terminated byte string and convert to an integer value using strtol()
or a related function. (See INT06-C. Use strtol() or a related function to convert a string token to an integer.)
Noncompliant Code Example
This noncompliant code example uses the scanf()
function to read a string from stdin
and convert it to a long
. The scanf()
and fscanf()
functions have undefined behavior if the value of the result of this operation cannot be represented as an integer.
long sl; if (scanf("%ld", &sl) != 1) { /* handle error */ }
In general, do not use scanf()
to parse integers or floating-point numbers from input strings because the input could contain numbers not representable by the argument type.
Compliant Solution (Linux)
This compliant example uses the Linux scanf()
implementation's built-in error handling to validate input. On Linux platforms, scanf()
sets errno
to ERANGE
if the result of integer conversion cannot be represented within the size specified by the format string [Linux 2008]. Note that this is a platform-dependent solution. Therefore, it should be used only where portability is not a concern.
long sl; errno = 0; if (scanf("%ld", &sl) != 1) { /* handle error */ } else if (ERANGE == errno) { if (puts("number out of range\n") == EOF) { /* Handle error */ } }
Compliant Solution
This compliant example uses fgets()
to input a string and strtol()
to convert the string to an integer. Error checking is provided to make sure the value is a valid integer in the range of long
.
char buff[25]; char *end_ptr; long sl; if (fgets(buff, sizeof(buff), stdin) == NULL) { if (puts("EOF or read error\n") == EOF) { /* Handle error */ } } else { errno = 0; sl = strtol(buff, &end_ptr, 10); if (ERANGE == errno) { if (puts("number out of range\n") == EOF) { /* Handle error */ } } else if (end_ptr == buff) { if (puts("not valid numeric input\n") == EOF) { /* Handle error */ } } else if ('\n' != *end_ptr && '\0' != *end_ptr) { if (puts("extra characters on input line\n") == EOF) { /* Handle error */ } } }
Note that this solution treats any trailing characters, including whitespace characters, as an error condition.
Risk Assessment
Although it is relatively rare for a violation of this recommendation to result in a security vulnerability, it can easily result in lost or misinterpreted data.
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
INT05-C | medium | probable | high | P4 | L3 |
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
Fortify SCA | V. 5.0 |
| Can detect violations of this recommendation with the CERT C Rule Pack. |
Compass/ROSE |
|
| Can detect violations of this recommendation. In particular, it notes uses of the |
PRQA QA-C | Unable to render {include} The included page could not be found. | Fully implemented |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
CERT C++ Secure Coding Standard: INT05-CPP. Do not use input functions to convert character data if they cannot handle all possible inputs
ISO/IEC 9899:2011 Section 7.22.1.4, "The strtol
, strtoll
, strtoul
, and strtoull
functions," and Section 7.21.6, "Formatted input/output functions"
MITRE CWE: CWE-192, "Integer coercion error"
MITRE CWE: CWE-197, "Numeric truncation error"
Bibliography
[Klein 2002]
[Linux 2008] scanf(3)