Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated references from C11->C23

The majority of the standard library functions, including I/O functions and memory allocation functions, return either a valid value or a value of the correct return type that indicates an error (for example, −1 or a null pointer). Assuming that all calls to such functions will succeed and failing to check the return value for an indication of an error is a dangerous practice that may lead to unexpected or undefined behavior when an error occurs. It is essential that programs detect and appropriately handle all errors in accordance with an error-handling policy, as discussed in ERR00-C. Adopt and implement a consistent and comprehensive error-handling policy.

The successful completion or failure of each of the standard library functions listed in the following table shall be determined either by comparing the function’s return value with the value listed in the column labeled “Error Return” or by calling one of the library functions mentioned in the footnotes.

Standard Library Functions

Function

Successful Return

Error Return

aligned_alloc()

Pointer to space

NULL

asctime_s()

0

Nonzero

at_quick_exit()

0

Nonzero

atexit()

0

Nonzero

bsearch()

Pointer to matching element

NULL

bsearch_s()

Pointer to matching element

NULL

btowc()

Converted wide character

WEOF

c16rtomb()

Number of bytes

(size_t)(-1)

c32rtomb()

Number of bytes

(size_t)(-1)

calloc()

Pointer to space

NULL

clock()

Processor time

(clock_t)(-1)

cnd_broadcast()

thrd_success

thrd_error

cnd_init()

thrd_success

thrd_nomem or thrd_error

cnd_signal()

thrd_success

thrd_error

cnd_timedwait()

thrd_success

thrd_timedout or thrd_error

cnd_wait()

thrd_success

thrd_error

ctime_s()

0

Nonzero

fclose()

0

EOF (negative)

fflush()

0

EOF (negative)

fgetc()

Character read

EOF1

fgetpos()

0

Nonzero, errno > 0

fgets()

Pointer to string

NULL

fgetwc()

Wide character read

WEOF1

fopen()

Pointer to stream

NULL

fopen_s()

0

Nonzero

fprintf()

Number of characters (nonnegative)

Negative

fprintf_s()

Number of characters (nonnegative)

Negative

fputc()

Character written

EOF2

fputs()

Nonnegative

EOF (negative)

fputwc()Wide character written WEOF

fputws()

Nonnegative

EOF (negative)

fread()

Elements read

Elements read

freopen()

Pointer to stream

NULL

freopen_s()

0

Nonzero

fscanf()

Number of conversions (nonnegative)

EOF (negative)

fscanf_s()

Number of conversions (nonnegative)

EOF (negative)

fseek()

0

Nonzero

fsetpos()

0

Nonzero, errno > 0

ftell()

File position

−1L, errno > 0

fwprintf()

Number of wide characters (nonnegative)

Negative

fwprintf_s()

Number of wide characters (nonnegative)

Negative

fwrite()

Elements written

Elements written

fwscanf()

Number of conversions (nonnegative)

EOF (negative)

fwscanf_s()

Number of conversions (nonnegative)

EOF (negative)

getc()

Character read

EOF1

getchar()

Character read

EOF1

getenv()

Pointer to string

NULL

getenv_s()

Pointer to string

NULL

gets_s()

Pointer to string

NULL

getwc()

Wide character read

WEOF

getwchar()

Wide character read

WEOF

gmtime()

Pointer to broken-down time

NULL

gmtime_s()

Pointer to broken-down time

NULL

localtime()

Pointer to broken-down time

NULL

localtime_s()

Pointer to broken-down time

NULL

malloc()

Pointer to space

NULL

mblen(), s != NULL

Number of bytes

−1

mbrlen(), s != NULL

Number of bytes or status

(size_t)(-1)

mbrtoc16()

Number of bytes or status

(size_t)(-1), errno == EILSEQ

mbrtoc32()

Number of bytes or status

(size_t)(-1), errno == EILSEQ

mbrtowc(), s != NULL

Number of bytes or status

(size_t)(-1), errno == EILSEQ

mbsrtowcs()

Number of non-null elements

(size_t)(-1), errno == EILSEQ

mbsrtowcs_s()

0

Nonzero

mbstowcs()

Number of non-null elements

(size_t)(-1)

mbstowcs_s()

0

Nonzero

mbtowc(), s != NULL

Number of bytes

−1

memchr()

Pointer to located character

NULL

mktime()

Calendar time

(time_t)(-1)

mtx_init()

thrd_success

thrd_error

mtx_lock()

thrd_success

thrd_error

mtx_timedlock()

thrd_success

thrd_timedout or thrd_error

mtx_trylock()

thrd_success

thrd_busy or thrd_error

mtx_unlock()

thrd_success

thrd_error

printf_s()

Number of characters (nonnegative)

Negative

putc()

Character written

EOF2

putwc()

Wide character written

WEOF

raise()

0

Nonzero

realloc()

Pointer to space

NULL

remove()

0

Nonzero

rename()

0

Nonzero

setlocale()

Pointer to string

NULL

setvbuf()

0

Nonzero

scanf()

Number of conversions (nonnegative)

EOF (negative)

scanf_s()

Number of conversions (nonnegative)

EOF (negative)

signal()

Pointer to previous function

SIG_ERR, errno > 0

snprintf()

Number of characters that would be written (nonnegative)

Negative

snprintf_s()

Number of characters that would be written (nonnegative)

Negative

sprintf()

Number of non-null characters written

Negative

sprintf_s()

Number of non-null characters written

Negative

sscanf()

Number of conversions (nonnegative)

EOF (negative)

sscanf_s()

Number of conversions (nonnegative)

EOF (negative)

strchr()

Pointer to located character

NULL

strerror_s()

0

Nonzero

strftime()

Number of non-null characters

0

strpbrk()

Pointer to located character

NULL

strrchr()

Pointer to located character

NULL

strstr()

Pointer to located string

NULL

strtod()

Converted value

0, errno == ERANGE

strtof()

Converted value

0, errno == ERANGE

strtoimax()

Converted value

INTMAX_MAX or INTMAX_MIN, errno == ERANGE

strtok()

Pointer to first character of a token

NULL

strtok_s()

Pointer to first character of a token

NULL

strtol()

Converted value

LONG_MAX or LONG_MIN, errno == ERANGE

strtold()

Converted value

0, errno == ERANGE

strtoll()

Converted value

LLONG_MAX or LLONG_MIN, errno == ERANGE

strtoumax()

Converted value

UINTMAX_MAX, errno == ERANGE

strtoul()

Converted value

ULONG_MAX, errno == ERANGE

strtoull()

Converted value

ULLONG_MAX, errno == ERANGE

strxfrm()

Length of transformed string

>= n

swprintf()

Number of non-null wide characters

Negative

swprintf_s()

Number of non-null wide characters

Negative

swscanf()

Number of conversions (nonnegative)

EOF (negative)

swscanf_s()

Number of conversions (nonnegative)

EOF (negative)

thrd_create()

thrd_success

thrd_nomem or thrd_error

thrd_detach()

thrd_success

thrd_error

thrd_join()

thrd_success

thrd_error

thrd_sleep()

0

Negative

time()

Calendar time

(time_t)(-1)

timespec_get()

Base

0

tmpfile()

Pointer to stream

NULL

tmpfile_s()

0

Nonzero

tmpnam()

Non-null pointer

NULL

tmpnam_s()

0

Nonzero

tss_create()

thrd_success

thrd_error

tss_get()

Value of thread-specific storage

0

tss_set()

thrd_success

thrd_error

ungetc()

Character pushed back

EOF (see below)

ungetwc()

Character pushed back

WEOF

vfprintf()

Number of characters (nonnegative)

Negative

vfprintf_s()

Number of characters (nonnegative)

Negative

vfscanf()

Number of conversions (nonnegative)

EOF (negative)

vfscanf_s()

Number of conversions (nonnegative)

EOF (negative)

vfwprintf()

Number of wide characters (nonnegative)

Negative

vfwprintf_s()

Number of wide characters (nonnegative)

Negative

vfwscanf()

Number of conversions (nonnegative)

EOF (negative)

vfwscanf_s()

Number of conversions (nonnegative)

EOF (negative)

vprintf_s()

Number of characters (nonnegative)

Negative

vscanf()

Number of conversions (nonnegative)

EOF (negative)

vscanf_s()

Number of conversions (nonnegative)

EOF (negative)

vsnprintf()

Number of characters that would be written (nonnegative)

Negative

vsnprintf_s()

Number of characters that would be written (nonnegative)

Negative

vsprintf()

Number of non-null characters (nonnegative)

Negative

vsprintf_s()

Number of non-null characters (nonnegative)

Negative

vsscanf()

Number of conversions (nonnegative)

EOF (negative)

vsscanf_s()

Number of conversions (nonnegative)

EOF (negative)

vswprintf()

Number of non-null wide characters

Negative

vswprintf_s()

Number of non-null wide characters

Negative

vswscanf()

Number of conversions (nonnegative)

EOF (negative)

vswscanf_s()

Number of conversions (nonnegative)

EOF (negative)

vwprintf_s()

Number of wide characters (nonnegative)

Negative

vwscanf()

Number of conversions (nonnegative)

EOF (negative)

vwscanf_s()

Number of conversions (nonnegative)

EOF (negative)

wcrtomb()

Number of bytes stored

(size_t)(-1)

wcschr()

Pointer to located wide character

NULL

wcsftime()

Number of non-null wide characters

0

wcspbrk()

Pointer to located wide character

NULL

wcsrchr()

Pointer to located wide character

NULL

wcsrtombs()

Number of non-null bytes

(size_t)(-1), errno == EILSEQ

wcsrtombs_s()

0

Nonzero

wcsstr()

Pointer to located wide string

NULL

wcstod()

Converted value

0, errno == ERANGE

wcstof()

Converted value

0, errno == ERANGE

wcstoimax()

Converted value

INTMAX_MAX or INTMAX_MIN, errno == ERANGE

wcstok()

Pointer to first wide character of a token

NULL

wcstok_s()

Pointer to first wide character of a token

NULL

wcstol()

Converted value

LONG_MAX or LONG_MIN, errno == ERANGE

wcstold()

Converted value

0, errno == ERANGE

wcstoll()

Converted value

LLONG_MAX or LLONG_MIN, errno == ERANGE

wcstombs()

Number of non-null bytes

(size_t)(-1)

wcstombs_s()

0

Nonzero

wcstoumax()

Converted value

UINTMAX_MAX, errno == ERANGE

wcstoul()

Converted value

ULONG_MAX, errno == ERANGE

wcstoull()

Converted value

ULLONG_MAX, errno == ERANGE

wcsxfrm()

Length of transformed wide string

>= n

wctob()

Converted character

EOF

wctomb(), s != NULL

Number of bytes stored

−1

wctomb_s(), s != NULL

Number of bytes stored

−1

wctrans()

Valid argument to towctrans

0

wctype()

Valid argument to iswctype

0

wmemchr()

Pointer to located wide character

NULL

wprintf_s()

Number of wide characters (nonnegative)

Negative

wscanf()

Number of conversions (nonnegative)

EOF (negative)

wscanf_s()

Number of conversions (nonnegative)

EOF (negative)

Note: According to FIO35-C. Use feof() and ferror() to detect end-of-file and file errors when sizeof(int) == sizeof(char), callers should verify end-of-file and file errors for the functions in this table as follows:

...

The ungetc() function does not set the error indicator even when it fails, so it is not possible to check for errors reliably unless it is known that the argument is not equal to EOF.

The C Standard 7.31.3.10 paragraph 3 [ISO/IEC 9899:20112024] states that "one

 )ne wide character of pushback is guaranteed...

," so this should not be an issue if, at most, one character is ever pushed back before reading again. (See FIO13-C. Never push back anything other than one read character.)

...

Code Block
bgColor#FFCCCC
langc
#include <stdlib.h>
#include <string.h>
 
enum { SIG_DESC_SIZE = 32 };

typedef struct {
  char sig_desc[SIG_DESC_SIZE];
} signal_info;
 
void func(size_t num_of_records, size_t temp_num,
          const char *tmp2, size_t tmp2_size_bytes) {
  signal_info *start = (signal_info *)calloc(num_of_records,
                                          sizeof(signal_info));

  if (tmp2 == NULL) {
    /* Handle error */
  } else if (temp_num > num_of_records || temp_num == 0) {
    /* Handle error */
  } else if (tmp2_size_bytes < SIG_DESC_SIZE) {
    /* Handle error */
  }

  signal_info *point = start + temp_num - 1;
  memcpy(point->sig_desc, tmp2, SIG_DESC_SIZE);
  point->sig_desc[SIG_DESC_SIZE - 1] = '\0';
  /* ... */
  free(start);
}

...

Code Block
bgColor#ccccff
langc
#include <stdlib.h>
#include <string.h>

enum { SIG_DESC_SIZE = 32 };

typedef struct {
  char sig_desc[SIG_DESC_SIZE];
} signal_info;
 
void func(size_t num_of_records, size_t temp_num,
          const char *tmp2, size_t tmp2_size_bytes) {
  signal_info *start = (signal_info *)calloc(num_of_records,
                                           sizeof(signal_info));
  if (start == NULL) {
    /* Handle allocation error */
  } else if (tmp2 == NULL) {
    /* Handle error */
  } else if (temp_num > num_of_records || temp_num == 0) {
    /* Handle error */
  } else if (tmp2_size_bytes < SIG_DESC_SIZE) {
    /* Handle error */
  }

  signal_info *point = start + temp_num - 1; 
  memcpy(point->sig_desc, tmp2, SIG_DESC_SIZE);
  point->sig_desc[SIG_DESC_SIZE - 1] = '\0';
  /* ... */
  free(start);
}

...

ERR33-C-EX1: It is acceptable to ignore the return value of a function if:

  • that function cannot fail

...

  • .
  • its return value is inconsequential; that is, it does not indicate an error.
  • it is one of a handful of functions whose return values are not traditionally checked.

These functions are listed in the following table:, or when an error condition need not be diagnosed. The function's results should be explicitly cast to void to signify programmer intent. Return values from the functions in the following table do not need to be checked because their historical use has overwhelmingly omitted error checking and the consequences are not relevant to security.

Functions for which Return Values Need Not Be Checked

Function

Successful Return

Error Return

putchar()

Character written

EOF

putwchar()

Wide character written

WEOF

puts()

Nonnegative

EOF (negative)

putws()

Nonnegative

WEOF

printf(), vprintf()

Number of characters (nonnegative)

Negative

wprintf(), vwprintf()

Number of wide characters (nonnegative)

Negative

kill_dependency()The input parameter NA
memcpy(), wmemcpy()The destination input parameterNA
memmove(), wmemmove()The destination input parameter NA
strcpy(), wcscpy()The destination input parameter NA
strncpy(), wcsncpy()The destination input parameter NA 
strcat(), wcscat()The destination input parameter NA 
strncat(), wcsncat()The destination input parameter NA
memset(), wmemset()The destination input parameterNA 

Risk Assessment

Failing to detect error conditions can lead to unpredictable results, including abnormal program termination and denial-of-service attacks or, in some situations, could even allow an attacker to run arbitrary code.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

ERR33-C

High

Likely

Medium

P18

L1

Automated Detection

The return value of a call to fprintf() or one of its variants (vfprintf(), wfprintf(), vwfprintf()) or one of the file output functions fputc(), fputwc(), fputs(), fputws() may be ignored if the output is being directed to stdout or stderr . Otherwise, the return value must be checked.

If a function's return value is to be ignored, it is recommended that the function's return value should be explicitly cast to void to signify the programmer's intent:

Code Block
bgColor#ccccff
langc
int main() {
  (void) fprintf(stdout, "Hello, world\n"); // fprintf() return value safely ignored
}

Risk Assessment

Failing to detect error conditions can lead to unpredictable results, including abnormal program termination and denial-of-service attacks or, in some situations, could even allow an attacker to run arbitrary code.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

ERR33-C

High

Likely

Medium

P18

L1

Automated Detection

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V
error-information-unused
error-information-unused-computed
Partially checked
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-ERR33
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

LANG.FUNCS.IRV
LANG.ERRCODE.NOTEST
LANG.ERRCODE.NZ

Ignored return value
Missing Test of Error Code
Non-zero Error Code
Compass/ROSE

Can detect violations of this recommendation when checking for violations of EXP12-C. Do not ignore values returned by functions and EXP34-C. Do not dereference null pointers

Coverity
Include Page
Coverity_V
Coverity_V

MISRA C 2012 Rule 22.8

MISRA C 2012 Rule 22.9

MISRA C 2012 Rule 22.10

Implemented
Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C3200

C++3802, C++3803, C++3804

DF2820, DF2821, DF2822, DF2823, DF2824, DF2930, DF2931, DF2932, DF2933, DF2934


Klocwork
Include Page
Klocwork_V
Klocwork_V

NPD.CHECK.MUST
NPD.FUNC.MUST
SV.RVT.RETVAL_NOTTESTED


LDRA tool suite
Include Page
LDRA_V
LDRA_V

80 D

Partially implemented
Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V

CERT_C-ERR33-a
CERT_C-ERR33-b
CERT_C-ERR33-d

The value returned by a standard library function that may return an error should be used
The standard library functions for which return values need not be checked should be cast to 'void'
Always check the returned value of non-void function

Parasoft Insure++

Runtime analysis
PC-lint Plus

Include Page
PC-lint Plus_V
PC-lint Plus_V

534

Partially supported

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rule ERR33-C


Checks for:

  • Errno not checked
  • Return value of a sensitive function not checked
  • Unprotected dynamic memory allocation

Rule partially covered.

RuleChecker

Include Page
RuleChecker_V
RuleChecker_V

error-information-unusedPartially checked
TrustInSoft Analyzer

Include Page
TrustInSoft Analyzer_V
TrustInSoft Analyzer_V

pointer arithmeticExhaustively verified.

Tool

Version

Checker

Description

Astrée Include PageAstrée_VAstrée_V Supported, but no explicit checkerCodeSonar Include PageCodeSonar_VCodeSonar_V

LANG.FUNCS.IRV

Ignored return valueCompass/ROSE  

Can detect violations of this recommendation when checking for violations of EXP12-C. Do not ignore values returned by functions and EXP34-C. Do not dereference null pointers

Coverity Include PageCoverity_VCoverity_V

MISRA C 2012 Rule 22.8

MISRA C 2012 Rule 22.9

MISRA C 2012 Rule 22.10

ImplementedLDRA tool suite Include PageLDRA_VLDRA_V

80 D

Partially implementedParasoft C/C++test9.5CODSTA-122_{a,b}, BD-PB-NPPartially implementedPRQA QA-C++ Include Pagecplusplus:PRQA QA-C++_Vcplusplus:PRQA QA-C++_V

2820, 2821, 2822, 2823, 2824, 2930, 2931, 2932, 2933, 2934, 3802, 3803, 3804

 PRQA QA-C Include PagePRQA QA-C_vPRQA QA-C_v

3200

Partially implemented

Related Vulnerabilities

The vulnerability in Adobe Flash [VU#159523] arises because Flash neglects to check the return value from calloc(). Even when calloc() returns a null pointer, Flash writes to an offset from the return value. Dereferencing a null pointer usually results in a program crash, but dereferencing an offset from a null pointer allows an exploit to succeed without crashing the program.

...

Key here (explains table format and definitions)

Taxonomy

Taxonomy item

Relationship

CERT C Secure Coding StandardERR00-C. Adopt and implement a consistent and comprehensive error-handling policyPrior to 2018-01-12: CERT: Unspecified Relationship
CERT C Secure Coding StandardEXP34-C. Do not dereference null pointersPrior to 2018-01-12: CERT: Unspecified Relationship
CERT C Secure Coding StandardFIO13-C. Never push back anything other than one read characterPrior to 2018-01-12: CERT: Unspecified Relationship
CERT C Secure Coding StandardMEM04-C. Do not perform zero-length allocationsPrior to 2018-01-12: CERT: Unspecified Relationship
CERT C Secure Coding StandardMEM12-C. Consider using a goto chain when leaving a function on error when using and releasing resourcesPrior to 2018-01-12: CERT: Unspecified Relationship
CERT CERR10-CPP. Check for error conditionsPrior to 2018-01-12: CERT: Unspecified Relationship
CERT CFIO04-CPP. Detect and handle input and output errorsPrior to 2018-01-12: CERT: Unspecified Relationship
ISO/IEC TS 17961:2013Failing to detect and handle standard library errors [liberr]Prior to 2018-01-12: CERT: Unspecified Relationship
CWE 2.11CWE-252, Unchecked Return Value2017-07-06: CERT: Partial overlap
CWE 2.11CWE-253, Incorrect Check of Function Return Value2017-07-06: CERT: Partial overlap
CWE 2.11CWE-391, Unchecked Error Condition2017-07-06: CERT: Rule subset of CWE

CERT-CWE Mapping Notes

Key here for mapping notes

...

  • Ignoring return values of functions outside the C or POSIX standard libraries


Bibliography

[DHS 2006]Handle All Errors Safely
[Henricson 1997]Recommendation 12.1, "Check for All Errors Reported from Functions"
[ISO/IEC 9899:
2011
2024]Subclause 7.
21
31.
7
3.10, "The ungetc Function"
[VU#159523]
 

...



...