CertC-ERR07

Prefer functions that support error checking over equivalent functions that don’t

Required inputs: IR

When you 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
Alternative
Comments
atof strtod No error indication, undefined behavior on error
atoi strtol No error indication, undefined behavior on error
atol strtol No error indication, undefined behavior on error
atoll strtoll No error indication, undefined behavior on error
rewind fseek No error indication, silent failure on error
setbuf setvbuf No error indication, silent failure on error
ctime asctime/ localtime  Undefined behavior if  localtime fails 
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 as follows:

Call Equivalent on Success
atoi(nptr) (int)strtol(nptr, (char **)NULL, 10)
atol(nptr) strtol(nptr, (char **)NULL, 10)
atoll(nptr) 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. (See undefined behavior 119 of Annex J of the C Standard.)
  • 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:

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;
  }
}

Both the noncompliant code example and the compliant solution are taken from ERR34-C. Detect 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():

char *file_name;
FILE *fp;

/* Initialize file_name */

fp = fopen(file_name, "r");
if (fp == NULL) {
  /* Handle open error */
}

/* Read data */

rewind(fp);

/* Continue */

It is impossible to determine if rewind() succeeded.

Compliant Solution ( fseek())

This compliant solution uses fseek() instead of rewind() and checks to see if the operation succeeded:

char *file_name;
FILE *fp;

/* Initialize file_name */

fp = fopen(file_name, "r");
if (fp == NULL) {
  /* Handle open error */
}

/* Read data */

if (fseek(fp, 0L, SEEK_SET) != 0) {
  /* Handle repositioning error */
}

/* Continue */
Noncompliant Code Example ( setbuf())

This noncompliant code example calls setbuf() with a buf argument of NULL:

FILE *file;
/* Setup file */
setbuf(file, NULL);
/* ... */

It is not possible to determine if the call to setbuf() succeeded.

Implementation Details

On 4.2BSD and 4.3BSD systems, setbuf() always uses a suboptimal buffer size and should be avoided.

Compliant Solution ( setvbuf())

This compliant solution calls setvbuf(), which returns nonzero if the operation failed:

FILE *file;
char *buf = NULL;
/* Setup file */
if (setvbuf(file, buf, buf ? _IOFBF : _IONBF, BUFSIZ) != 0) {
  /* Handle error */
}
/* ... */
Risk Assessment

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 Remediation Cost Priority Level
ERR07-C Medium Probable Medium P8 L2
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()"
Excerpt from SEI CERT C Coding Standard: Rules for Developing Safe, Reliable, and Secure Systems (2016 Edition) and SEI CERT C Coding Standard [https://cmu-sei.github.io/secure-coding-standards/sei-cert-c-coding-standard/recommendations/error-handling-err/err07-c], Copyright (C) 1995-2026 Carnegie Mellon University. See section 9.4. "3rd-Party Licenses" in the documentation for full details.

Possible Messages

Key

Text

Severity

Disabled

error_checking_alternative

Prefer functions that support error checking over equivalent functions that don’t (i.e., replace ‘{}’ by ‘{}’).

None

False

Options

replacements

replacements

Type: dict[str, str]

Default:

{
   'atof': 'strtod',
   'atoi': 'strtol',
   'atol': 'strtol',
   'atoll': 'strtoll',
   'ctime': 'asctime/localtime',
   'rewind': 'fseek',
   'setbuf': 'setvbuf'
}
Mapping of non-error-checking functions to error-checking replacements.