The 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 .Use strtol() or a related function to convert a string token to an integer. Likewise, use strtof() or a related function to convert a string token to a floating-point number. These functions provide more robust error handling than alternative solutions.using a C Standard Library function.
The strtol(), strtoll(), strtoimax(), strtoul(), strtoull(), strtofstrtoumax(), 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, 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 type such as signed int, signed short, and signed char, testing the result against the range limits for that type. Likewise, 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 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())
...
The atoi(), atol(), atoll(), and atof() functions convert the initial portion of a string token to int, long int, long long int, and double representation 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) |
...
- 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.
...
Compliant Solution (strtol())
The strtol(), strtoll(), strtoimax()), strtoul(), strtoull(), strtoumax(), strtof(), strtod(), and strtold() functions convert a null-terminated byte string to long int, long long int, intmax_t, unsigned long int, unsigned long long int, floatuintmax_t, float, double, and long double representation, respectively.
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
void func(const char *buff) {
char *end;
int si;
errno = 0;
const long sl = strtol(buff, &end, 10);
if (end == buff) {
(void) fprintf(stderr, "%s: not a decimal number\n", buff);
} else if ('\0' != *end) {
(void) fprintf(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_MAX) {
(void) fprintf(stderr, "%ld greater than INT_MAX\n", sl);
} else if (sl < INT_MIN) {
(void) fprintf(stderr, "%ld less than INT_MIN\n", sl);
} else {
si = (int)sl;
/* Process si */
}
}
|
...
It is rare for a violation of this rule to result in a security vulnerability 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 | 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:
|
5.0
| Helix QAC |
| C5030 C++5016 | |||||||
| Klocwork |
| CERT.ERR.CONV.STR_TO_NUM |
| LDRA tool suite |
| 44 S | Fully implemented | ||||||
| Parasoft C/C++test |
-wc atol
| 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.
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- |
CWE-79, Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
CWE-89, Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
CWE-91, XML Injection (aka Blind XPath Injection)
CWE-94, Improper Control of Generation of Code ('Code Injection')
CWE-114, Process Control
CWE-601, URL Redirection to Untrusted Site ('Open Redirect')
CWE-676, Use of potentially dangerous function
CWE-20, Insufficient input validation
Bibliography
...
| 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] |
...