...
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.
Code Block | ||
---|---|---|
| ||
long sl;
if (scanf("%ld", &sl) != 1) {
/* handle error */
}
|
...
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 that the value is a valid integer in the range of long
.
Code Block | ||
---|---|---|
| ||
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 white-space characters, as an error condition.
Compliant Solution
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 integer conversion would cause overflow with the given type. Note that this is a platform dependent solution. Therefore, this should only be used where portability is not a concern.
Code Block | ||
---|---|---|
| ||
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 */
}
}
|
Risk Assessment
While 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.
...