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
, and 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
, and unsigned char
, and test 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.
Noncompliant Code Example (atoi()
)
This noncompliant 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
- return 0 if the string does not represent an integer, which is indistinguishable from a correctly formatted, zero-denoting input string.
Noncompliant Example (sscanf()
)
This noncompliant example uses the sscanf()
function to convert a string token to an integer. The sscanf()
function has the same limitations as atoi()
.
int matches; int si; if (argc > 1) { matches = sscanf(argv[1], "%d", &si); if (matches != 1) { /* Handle error */ } }
The sscanf()
function does return the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure. However, sscanf()
fails to report the other errors reported by strtol()
, such as overflow.
Compliant Solution (strtol()
)
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 ((sl == LONG_MIN || sl == LONG_MAX) && errno != 0) { perror("strtol error"); } else if (end_ptr == argv[1]) { if (puts("error encountered during conversion") == EOF) { /* Handle error */ } } else if (sl > INT_MAX) { printf("%ld too large!\n", sl); } else if (sl < INT_MIN) { printf("%ld too small!\n", sl); } else if ('\0' != *end_ptr) { if (puts("extra characters on input line\n") == EOF) { /* Handle error */ } } else { si = (int)sl; } }
Risk Assessment
While it is 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 |
---|---|---|---|---|---|
INT06-C |
medium |
probable |
medium |
P8 |
L2 |
Automated Detection
Fortify SCA Version 5.0 with the CERT C Rule Pack can detect violations of this recommendation.
Compass/ROSE can detect violations of this recommendation by flagging invocations of the following functions:
atoi()
scanf()
,fscanf()
,sscanf()
- others?
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Other Languages
This rule appears in the C++ Secure Coding Standard as INT06-CPP. Use strtol() or a related function to convert a string token to an integer.
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"
[[MITRE 07]] CWE ID 676, "Use of Potentially Dangerous Function," and CWE ID 20, "Insufficient Input Validation"