Use strtol() or a related function to convert a string token to an integer. These functions provide more robust error handling than alternative solutionsThe process of parsing an integer or floating-point number from a string can produce many errors. The string might not contain a number. It might contain a number of the correct type that is out of range (such as an integer that is larger than INT_MAX). The string may also contain extra information after the number, which may or may not be useful after the conversion. These error conditions must be detected and addressed when a string-to-number conversion is performed using a C Standard Library function.
The strtol(), strtoll(), strtoimax(), strtoul(), and strtoull() functions , strtoumax(), strtof(),strtod(), and strtold() functions convert the initial portion of a null-terminated byte string to a long int, long long int, intmax_t, unsigned long int, and unsigned long long int, uintmax_t, float, double, and long double representation, respectively.
Use one of the C Standard Library strto*() functions to parse an integer or floating-point number from a string. These functions provide more robust error handling than alternative solutions. Also, use the strtol() function to convert to a smaller , signed integer types type such as signed int, signed short, and signed char, testing the result against the range limits for that type. Use Likewise, use the strtoul() function to convert to a smaller unsigned integer type such as unsigned int, unsigned short, and unsigned char, testing and test the result against the range limits for that type.These These range tests do nothing if the smaller type happens to have the same size and representation on for a particular compilerimplementation.
...
Noncompliant Code Example (atoi())
This non-compliant noncompliant code example converts the string token stored in the static array buff to a signed integer value using the atoi() function.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdlib.h> void func(const char *buff) { int si; if (argc > 1buff) { si = atoi(argv[1]buff); } else { /* Handle error */ } } |
The atoi(), atol(), atoll(), and atollatof() functions convert the initial portion of a string token to int, long int, and long long int, and double representation, respectively. Except for the behavior on error ([ISO/IEC 9899:2024], s7.24.1.2), they are equivalent to
| Code Block |
|---|
atoi: (int)strtol(nptr, (char **)NULL, 10) atol: strtol(nptr, (char **)NULL, 10) atoll: strtoll(nptr, (char **)NULL, 10) atof: strtod(nptr, (char **)NULL) |
Unfortunately, atoi() and related functions lack a mechanism for reporting errors for invalid values. Specifically, the atoi(), atol(), and atoll() functionsthese functions:
- do not need to set
errnoon an error; - have have undefined behavior 16 if the value of the result cannot be represented;
- return 0 (or 0.0) if the string does not represent an integer (or decimal), which is indistinguishable from a correctly formatted, zero-denoting input string.
Non-Compliant Example
Noncompliant Example (sscanf())
This noncompliant 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().:
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h> void func(const char *buff) { int matches; int si; if (argc > 1buff) { matches = sscanf(argv[1]buff, "%d", &si); if (matches != 1) { /* handleHandle error */ } } else { /* Handle error */ } } |
The sscanf() function does return returns the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero 0 in the event of an early matching failure. However, sscanf() fails to report the other errors reported by strtol(), such as numeric overflow.
Compliant Solution (strtol())
The The strtol(), strtoll(), strtoimax()), strtoul(), and strtoull() functions strtoull(), strtoumax(), strtof(), strtod(), and strtold() functions convert a null-terminated byte string to to long int, long long int, intmax_t, unsigned long int, and unsigned long long int representation, uintmax_t, float, double, and long double 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.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <errno.h> long sl; int si; char *end_ptr; if (argc > 1) { #include <limits.h> #include <stdlib.h> #include <stdio.h> void func(const char *buff) { char *end; int si; errno = 0; const long sl = strtol(argv[1]buff, &end_ptr, 10); if ((slend == LONG_MINbuff) { || (sl == LONG_MAXvoid) || (end_ptr == argv[1])) { if (errno != 0fprintf(stderr, "%s: not a decimal number\n", buff); } else if ('\0' != *end) { (void) perror("strtol error"); } else { puts("error encountered during conversion"); } } else if (sl > INT_MAX) { printf("%ld too large!\n", slfprintf(stderr, "%s: extra characters at end of input: %s\n", buff, end); } else if ((LONG_MIN == sl || LONG_MAX == sl) && ERANGE == errno) { (void) fprintf(stderr, "%s out of range of type long\n", buff); } else if (sl <> INT_MINMAX) { printf((void) fprintf(stderr, "%ld greater too small!than INT_MAX\n", sl); } else if ('\0' != *end_ptrsl < INT_MIN) { puts("extra characters on input line\n"(void) fprintf(stderr, "%ld less than INT_MIN\n", sl); } else { si = (int)sl; /* Process si */ } } |
Risk Assessment
While it It is relatively rare for a violation of this rule to result in a security vulnerability, it could more unless it occurs in security-sensitive code. However, violations of this rule can easily result in lost or misinterpreted data.
Recommendation | Severity | Likelihood | Detectable |
|---|
Repairable | Priority | Level |
|---|
ERR34- |
C | Medium |
Unlikely |
Yes |
Yes |
P6 | L2 |
Automated Detection
Tool |
|---|
Fortify SCA Version 5.0 with the CERT C Rule Pack can detect violations of this recommendation.
...
Version | Checker | Description | |||||||
|---|---|---|---|---|---|---|---|---|---|
| Axivion Bauhaus Suite |
| CertC-ERR34 | |||||||
| Clang |
| cert-err34-c | Checked by clang-tidy | ||||||
| CodeSonar |
| BADFUNC.ATOF (customization) | Use of atof Users can add custom checks for uses of other undesirable conversion functions. | ||||||
| Compass/ROSE | Can detect violations of this recommendation by flagging invocations of the following functions:
|
...
| |||||||||
| Helix QAC |
| C5030 C++5016 | |||||||
| Klocwork |
| CERT.ERR.CONV.STR_TO_NUM | |||||||
| LDRA tool suite |
| 44 S | Fully implemented | ||||||
| Parasoft C/C++test |
| CERT_C-ERR34-a | The 'atof', 'atoi', 'atol' and 'atoll' functions from the 'stdlib.h' or 'cstdlib' library should not be used | ||||||
| PC-lint Plus |
| 586 | Assistance provided | ||||||
| CERT C: Rule ERR34-C | Checks for unsafe conversion from string to numeric value (rule fully covered) | |||||||
| SonarQube C/C++ Plugin |
| S989 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
| Wiki Markup |
|---|
\[[Klein 02|AA. C References#Klein 02]\]
\[[ISO/IEC 9899:1999|AA. C References#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" |
Related Guidelines
Key here (explains table format and definitions)
Taxonomy | Taxonomy item | Relationship |
|---|---|---|
| CERT C | INT06-CPP. Use strtol() or a related function to convert a string token to an integer | Prior to 2018-01-12: CERT: Unspecified Relationship |
| CWE 2.11 | CWE-676, Use of potentially dangerous function | 2017-05-18: CERT: Rule subset of CWE |
| CWE 2.11 | CWE-758 | 2017-06-29: CERT: Partial overlap |
CERT-CWE Mapping Notes
Key here for mapping notes
CWE-20 and ERR34-C
Intersection( ERR34-C, CWE-20) = Ø
CERT C does not define the concept of ‘input validation’. String-to-integer conversion (ERR34-C) may qualify as input validation, but this is outside the scope of the CERT rule.
CWE-391 and ERR34-C
CWE-391 = Union( ERR34-C, list) where list =
- Failure to errors outside of string-to-number conversion functions
CWE-676 and ERR34-C
- Independent( ENV33-C, CON33-C, STR31-C, EXP33-C, MSC30-C, ERR34-C)
- ERR34-C implies that string-parsing functions (eg atoi() and scanf()) are dangerous.
- CWE-676 = Union( ERR34-C, list) where list =
- Invocation of dangerous functions besides the following:
- atoi(), atol(), atoll(), atof(), The scanf()family
CWE-758 and ERR34-C
Independent( INT34-C, INT36-C, MSC37-C, FLP32-C, EXP33-C, EXP30-C, ERR34-C, ARR32-C)
Intersection( CWE-758, ERR34-C) =
- Undefined behavior arising from a non-representable numeric value being parsed by an ato*() or scanf() function
CWE-758 – ERR34-C =
- Undefined behavior arising from using a function outside of the ato*() or scanf() family
ERR34-C – CWE-758 =
- The ato*() or scanf() family receives input that is not a number when trying to parse one
Bibliography
| [ISO/IEC 9899:2024] | Subclause 7.24.1, "Numeric conversion functions" |
| [Klein 2002] |
...
INT05-A. Do not use input functions to convert character data if they cannot handle all possible inputs 04. Integers (INT) INT07-A. Use only explicitly signed or unsigned char type for numeric values