Use strtol()
or a related function to convert a string token to an integer. These functions provide more robust error handling than alternative solutions.
The strtol()
, strtoll()
, strtoul()
, and strtoull()
functions convert the initial portion of a null-terminated byte string to long int
, long long int
, unsigned long int
, and unsigned long long int
representation, respectively.
Use the strtol()
function to convert to smaller, signed integer types such as signed int
, signed short
or signed char
), testing the result against the range limits for that type.
Use the strtoul()
function to convert to a smaller unsigned integer type such as unsigned int
, unsigned short
, or unsigned char
, testing the result against the range limits for that type.
These range tests do nothing if the smaller type happens to have the same size and representation on a particular compiler.
Non-Compliant Code Example
This non-compliant code example converts the string token stored in the static array buff
to a signed integer value using the atoi()
function.
int si; if (argc > 1) { si = atoi(argv[1]); }
The atoi()
, atol()
, and atoll()
functions convert the initial portion of a string token to int
, long int
, and long long int
representation, respectively. Except for the behavior on error, they are equivalent to
atoi: (int)strtol(nptr, (char **)NULL, 10) atol: strtol(nptr, (char **)NULL, 10) atoll: strtoll(nptr, (char **)NULL, 10)
Unfortunately, atoi()
and related functions lack a mechanism for reporting errors for invalid values. Specifically, the atoi()
, atol()
, and atoll()
functions:
- do not need to set
errno
on an error - have undefined behavior if the value of the result cannot be represented
Non-Compliant Example
This non-compliant example uses the sscanf()
function to convert a string token to an integer. The sscanf()
function has the same limitations as atoi()
.
int si; if (argc > 1) { sscanf(argv[1], "%d", &si); }
Compliant Solution
The strtol()
, strtoll()
, strtoul()
, and strtoull()
functions convert a null-terminated byte string to long int
, long long int
, unsigned long int
, and unsigned long long int
representation, respectively.
This compliant solution uses strtol()
to convert a string token to an integer and ensures that the value is in the range of int
.
long sl; int si; char *end_ptr; if (argc > 1) { errno = 0; sl = strtol(argv[1], &end_ptr, 10); if (ERANGE == errno) { puts("number out of range\n"); } else if (sl > INT_MAX) { printf("%ld too large!\n", sl); } else if (sl < INT_MIN) { printf("%ld too small!\n", sl); } else if (end_ptr == argv[1]) { puts("invalid numeric input\n"); } else if ('\0' != *end_ptr) { puts("extra characters on input line\n"); } else { si = (int)sl; } }
Risk Assessment
While it is relatively rare for a violation of this rule to result in a security vulnerability, it could more easily result in loss or misinterpreted data.
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
INT06-A |
2 (medium) |
2 (probable) |
2 (medium) |
P8 |
L2 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[Klein 02]]
[[ISO/IEC 9899-1999]] Section 7.20.1.4, "The strtol, strtoll, strtoul, and strtoull functions," Section 7.20.1.2, "The atoi, atol, and atoll functions," and Section 7.19.6.7, "The sscanf function"