When you has have a choice of two functions to accomplish the same task, prefer the one with better error checking and reporting.
The following table shows a list of C standard library functions that provide limited or no error checking and reporting along with preferable alternatives:
Function | Preferable | Comments |
|---|---|---|
|
| No error indication, undefined behavior on error |
|
| No error indication, undefined behavior on error |
|
| No error indication, undefined behavior on error |
|
| No error indication, undefined behavior on error |
|
| No error indication, silent failure on error |
|
| No error indication, silent failure on error |
ctime | asctime/localtime | Undefined behavior if |
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.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
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
...
as follows:
Call | Equivalent on Success |
|---|---|
|
|
...
|
...
|
...
|
...
|
|
...
|
...
|
...
|
...
|
|
...
|
...
|
...
|
...
Unfortunately, atoi() and related functions lack a mechanism for reporting errors for invalid values. Specifically, the atoi(), atol(), and atoll() functions
- do Do not need to set
errnoon an error. - have Have undefined behavior if the value of the result cannot be represented. (See undefined behavior 118 of Annex J of the C Standard.)
- Return return 0 if the string does not represent an integer , (which is indistinguishable from a correctly formatted, zero-denoting input string), but the C Standard only specifies the behavior of these functions on success.
See also MSC24-C. Do not use deprecated or obsolescent functions.
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.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
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) || (end_ptr == argv[1])) { if (&& errno != 0) { perror("strtol error"); } } else if (end_ptr else== argv[1]) { if (puts("error encountered during conversion") == EOF) { /* Handle Errorerror */ } } } 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 Errorerror */ } } else { si = (int)sl; } } |
Both the non-compliant noncompliant code example and compliant the compliant solution are taken from INT06ERR34-C. Use strtol() or a related function to convert a string token to an integerDetect errors when converting a string to a number.
Noncompliant Code Example (rewind())
This noncompliant code example sets the file position indicator of an input stream back to the beginning using rewind().:
| Code Block | ||||
|---|---|---|---|---|
| ||||
char *file_name; FILE *fp; /* initializeInitialize file_name */ fp = fopen(file_name, "r"); if (fp == NULL) { /* Handle open error */ } /* readRead data */ rewind(fp); /* continueContinue */ |
However, it It is impossible to determine if rewind() succeeded.
...
This compliant solution uses fseek() instead of rewind() and checks to see if the operation succeeded.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
char *file_name; FILE *fp; /* initializeInitialize file_name */ fp = fopen(file_name, "r"); if (fp == NULL) { /* Handle open error */ } /* readRead data */ if (fseek(fp, 0L, SEEK_SET) != 0) { /* Handle repositioning error */ } /* continueContinue */ |
Both the non-compliant code example and compliant solution are taken from FIO07-C. Prefer fseek() to rewind().
Noncompliant Code Example (setbuf())
This noncompliant code example calls setbuf() with a buf argument of NULL.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
FILE *file;
/* Setup file */
setbuf(file, NULL);
/* ... */
|
...
This compliant solution calls setvbuf(), which returns nonzero if the operation failed.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
FILE *file;
char *buf = NULL;
/* Setup file */
if (setvbuf(file, buf, buf ? _IOFBF : _IONBF, BUFSIZ) != 0) {
/* Handle error */
}
/* ... */
|
...
Risk Assessment
While it Although it is rare for a violation of this rule to result in a security vulnerability, it can easily result in lost or misinterpreted data.
Recommendation | Severity | Likelihood |
|---|
Detectable | Repairable | Priority | Level |
|---|
ERR07-C |
Medium | Probable |
Yes |
Yes |
P12 |
L1 |
Automated Detection
This rule in general cannot be detected, although various examples can be detected by simply scanning for functions that have equivalent functions with better error handling.
Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| Astrée |
| bad-function | Fully checked | ||||||
| Axivion Bauhaus Suite |
| CertC-ERR07 | |||||||
| Helix QAC |
| C5046 | |||||||
| LDRA tool suite |
| 44 S, 593 S, 594 S | Partially implemented | ||||||
| Parasoft C/C++test |
| CERT_C-ERR07-a | The 'atof', 'atoi', 'atol' and 'atoll' functions from the 'stdlib.h' or 'cstdlib' library should not be used | ||||||
| PC-lint Plus |
| 586 | Fully supported | ||||||
| RuleChecker |
| bad-function | Fully checked |
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," Section 7.19.6.7, "The {{sscanf}} function," Section 7.19.5.5, "The {{setbuf}} function", Section 7.19.9.2, "The fseek function"; 7.19.9.5, and "The rewind function"
\[[MITRE 07|AA. C References#MITRE 07]\] [CWE ID 676|http://cwe.mitre.org/data/definitions/676.html], "Use of Potentially Dangerous Function," and [CWE ID 20|http://cwe.mitre.org/data/definitions/20.html], "Insufficient Input Validation" |
Related Guidelines
| MITRE CWE | CWE-20, Improper Input Validation 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 |
Bibliography
| [Klein 2002] | "Bullet Proof Integer Input Using strtol()" |
...
12. Error Handling (ERR) ERR30-C. Set errno to zero before calling a library function known to set errno, and check errno only after the function returns a value indicating failure