 
                            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 using a C Standard Library function.
Use the strtol() or related function to convert a string to an integer. The strtol(), strtoll(),  strtoimax(), strtoul(),  and strtoull() functions strtoull(),  strtoumax(), strtof(),strtod(), and strtold() functions convert the initial portion of a null-terminated byte string  pointed  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.
Non-Compliant Example 1
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 range tests do nothing if the smaller type happens to have the same size and representation for a particular implementation.
Noncompliant Code Example (atoi())
This noncompliant This non-compliant 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) [25]; { int int_varsi; fgets if (buff,) { sizeof buff, stdin); int_var si = atoi(buff); } else { /* Handle error */ } } | 
The atoi(), atol(), atoll(), and atollatof() functions convert the initial portion of astring pointed 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
Non-Compliant Example 2
- ;
- 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.
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 problems limitations as atoi().:
| Code Block | ||||
|---|---|---|---|---|
| 
 | ||||
| #include <stdio.h> void func(const char *buff [25]) { int matches; int int_varsi; fgets if (buff, sizeof ) { matches = sscanf(buff, stdin); sscanf("%d", buff, &int_var); | 
Compliant Solution
The following compliant example uses strtol() to input an integer value and provides error checking to make sure that the value is a valid integer in the range of int.
| &si);
    if (matches != 1) {
      /* Handle error */
    }
  } else {
    /* Handle error */
  }
} | 
The sscanf() function returns the number of input items successfully matched and assigned, which can be fewer than provided for, or even 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 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, 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>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
 
void func(const char *buff) {
  char *end;
  int si;
   | ||||
| Code Block | ||||
| char buff [25]; char *end_ptr; long long_var; int int_var; fgets(buff, sizeof buff, stdin); errno = 0; long_var const long sl = strtol(buff, &end_ptr, 010); if (ERANGEend == errnobuff) { puts("number out of range\n"); } else if (long_var > INT_MAX (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) { printf("%ld too large! (void) fprintf(stderr, "%s out of range of type long\n", long_varbuff); } else if (long_varsl <> INT_MINMAX) { printf((void) fprintf(stderr, "%ld too small!greater than INT_MAX\n", long_varsl); } else if (end_ptr == buffsl < INT_MIN) { printf("not valid numeric input\n"); } (void) fprintf(stderr, "%ld less than INT_MIN\n", sl); } else { int_var si = (int)long_var; } | 
If you are attempting to convert a string to a smaller interger type (int, short, or signed char), then you only need test the result against the limits for that type. The tests do nothing if the smaller type happens to have the same size and representation on a particular compiler.
References
...
| sl;
    /* Process si */
  }
}
 | 
Risk Assessment
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 | ||||||
|---|---|---|---|---|---|---|---|---|---|
| Astrée | 
 | bad-function-use | Partially checked | ||||||
| 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) | |||||||
| RuleChecker | 
 | bad-function-use scanf-string-to-number | Partially checked | ||||||
| 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-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] | 
...
...