...
- Those that set
errno
and return an out-of-band error indicator - Those that set
errno
and return an in-band error indicator - Those that do not promise to set
errno
- Those with differing standards documentation
Library Functions that Set errno
and Return an Out-of-Band Error Indicator
The C Standard specifies that the functions listed in the following table set errno
and return an out-of-band error indicator. That is, their return value on error can never be returned by a successful call.
A program may set and check errno
for after invoking these library functions but is not required to do so. The program should not check the value of errno
without first verifying that the function returned an error indicator. For example, errno
should not be checked after calling signal()
without first ensuring that signal()
actually returned SIG_ERR
.
...
Function Name | Return Value |
|
---|---|---|
ftell() | -1L | Positive |
| Nonzero | Positive |
|
|
|
|
| Positive |
|
|
|
mbrtoc16() , mbrtoc32() | (size_t)(-1) | EILSEQ |
c16rtomb() , c32rtomb() | (size_t)(-1) | EILSEQ |
Library Functions that Set errno
and Return an In-Band Error Indicator
The C Standard specifies that the functions listed in the following table set errno
and return an in-band error indicator. That is, the return value when an error occurs is also a valid return value for successful calls. For example, the strtoul()
function returns ULONG_MAX
and sets errno
to ERANGE
if an error occurs. Because ULONG_MAX
is a valid return value, errno
must be used to check whether the only way to confirm that an error actually occurred. A program that uses errno
for error checking must set it to 0
before calling one of these library functions and then inspect errno
before a subsequent library function calloccurred when LONG_MAX is returned is to check errno
.
The fgetwc()
and fputwc()
functions return WEOF
in multiple cases, only one of which results in setting errno
. The string conversion functions will return the maximum or minimum representable value and set errno
to ERANGE
if the converted value cannot be represented by the data type. However, if the conversion cannot happen because the input is invalid, the function will return 0
, and the output pointer parameter will be assigned the value of the input pointer parameter, provided the output parameter is non-null.
...
A program that uses errno
for error checking a function that returns an in-band error indicator must set errno
to 0
before calling one of these library functions and then inspect errno
before a subsequent library function call.
Functions that Set errno
Set errno
and Return an In-Band Error Indicator
Function Name | Return Value |
|
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 0 or ±HUGE_VALL |
|
|
|
|
Library Functions that Do Not Promise to Set errno
The C Standard fails to document the behavior of errno
for some functions. For example, the setlocale()
function normally returns a null pointer in the event of an error, but no guarantees are made about setting errno
.
After calling one of these functions, a program should not rely solely on the value of errno
to determine if an error occurred. The function might have altered errno
, but this does not ensure that errno
will properly indicate an error condition.
Library Functions with Differing Standards Documentation
If the program does check errno
after calling one of these functions, it should set errno
to 0 before the function call.
Library Functions with Differing Standards Documentation
Some functions behave differently regarding errno
Some functions behave differently regarding errno
in various standards. The fopen()
function is one such example. When fopen()
encounters an error, it returns a null pointer. The C Standard makes no mention of errno
when describing fopen()
. However, POSIX.1 declares that when fopen()
encounters an error, it returns a null pointer and sets errno
to a value indicating the error [IEEE Std 1003.1-2013]. The implication is that a program conforming to C but not to POSIX (such as a Windows program) should not check errno
after calling fopen()
, but a POSIX program may check errno
if fopen()
returns a null pointer.
Library Functions and errno
The following uses of errno
are documented in the C Standard:
...
The POSIX.1 standard defines the use of errno
by many more functions (including the C standard library function). POSIX also has a small set of functions that are exceptions to the rule. These functions have no return value reserved to indicate an error, but they still set errno
on error. To detect an error, an application must set errno
to 0
before calling the function and check whether it is nonzero after the call. Affected functions include strcoll()
, strxfrm()
, strerror()
, wcscoll()
, wcsxfrm()
, and fwide()
. The C Standard allows these functions to set errno
to a nonzero value on success. Consequently, this type of error checking should be performed only on POSIX systems.
Noncompliant Code Example (strtoul()
)
This noncompliant code example fails to set errno
to 0
before invoking strtoul()
. If an error occurs, strtoul()
returns a valid value (ULONG_MAX
), so errno
is the only means of determining if strtoul()
ran successfully.
...
Any error detected in this manner may have occurred earlier in the program or may not represent an actual error.
Compliant Solution (strtoul()
)
This compliant solution sets errno
to 0
before the call to strtoul()
and inspects errno
after the call:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <errno.h> #include <limits.h> #include <stdlib.h> void func(const char *c_str) { unsigned long number; char *endptr; errno = 0; number = strtoul(c_str, &endptr, 0); if (endptr == c_str || (number == ULONG_MAX && errno == ERANGE)) { /* Handle error */ } else { /* Computation succeeded */ } } |
Noncompliant Code Example (
...
ftell()
)
This noncompliant code example may fail to diagnose errors because fopen()
might not set errno
even if an error occurs:, after calling ftell()
, examines errno
without first checking whether the out-of-band indicator returned by ftell()
indicates an error.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <errno.h> #include <stdio.h> void func(const char *filenameFILE* fp) { FILE *fileptr; errno = 0; fileptr = fopen(filename, "rb"ftell(fp); if (errno != 0) { /* Handle error */perror("ftell"); } } |
Compliant Solution (
...
ftell()
...
)
This compliant solution first detects that ftell()
failed using its out-of-band error indicator. Once an error has been confirmed, reading errno
(implicitly by using the perror()
function) is permitted.The C Standard makes no mention of errno
when describing fopen()
. In this compliant solution, the results of the call to fopen()
are used to determine failure and errno
is not checked:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <errno.h> #include <stdio.h> void func(const char *filenameFILE* fp) { FILE *fileptr = fopen(filename, "rb"); if (ftell(fileptrfp) == NULL-1) { /* An error occurred in fopen() */perror("ftell"); } } |
...
Noncompliant Code Example (fopen()
...
)
This noncompliant code example may fail to diagnose errors because fopen()
might not set errno
even if an error occurs:
In this compliant solution, errno
is checked only after an error has already been detected by another means:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <errno.h> #include <stdio.h> void func(const char *filename) { FILE *fileptr; errno = 0; fileptr = fopen(filename, "rb"); if (fileptrerrno !== NULL0) { /* Handle error */ An error occurred in fopen(); now it's valid * to examine errno. } } |
Compliant Solution (fopen()
, C)
The C Standard makes no mention of errno
when describing fopen()
. In this compliant solution, the results of the call to fopen()
are used to determine failure and errno
is not checked:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> void func(const char *filename) { FILE *fileptr = fopen(filename, "rb"); if (fileptr == NULL) { /*/ An error occurred in perrorfopen(filename); */ } } |
Risk Assessment
The improper use of errno
may result in failing to detect an error condition or in incorrectly identifying an error condition when none exists.
...
Rule
...
Severity
...
Likelihood
...
Remediation Cost
...
Priority
...
Level
...
ERR30-C
...
Medium
...
Probable
...
Medium
...
P8
...
L2
Compliant Solution (fopen()
, POSIX)
In this compliant solution, errno
is checked only after an error has already been detected by another means:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <errno.h>
#include <stdio.h>
void func(const char *filename) {
FILE *fileptr;
errno = 0;
fileptr = fopen(filename, "rb");
if (fileptr == NULL) {
/*
* An error occurred in fopen(); now it's valid
* to examine errno.
*/
perror(filename);
}
} |
Risk Assessment
The improper use of errno
may result in failing to detect an error condition or in incorrectly identifying an error condition when none exists.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ERR30-C | Medium | Probable | Medium | P8 | L2 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Astrée |
| errno-reset | Partially checked | ||||||
Axivion Bauhaus Suite |
| CertC-ERR30 | Fully implemented | ||||||
CodeSonar |
| LANG.STRUCT.RC | Redundant Condition | ||||||
Compass/ROSE | Could detect violations of this rule by ensuring that each library function is accompanied by the proper treatment of | ||||||||
Coverity |
| MISRA C 2012 Rule 22.8 MISRA C 2012 Rule 22.9 MISRA C 2012 Rule 22.10 | Implemented | ||||||
Helix QAC |
| C2500, C2501, C2502, C2503 C++3172, C++3173, C++3174, C++3175, C++3176, C++3177, C++3178, C++3179, C++3183, C++3184 | |||||||
Klocwork |
| CXX.ERRNO.NOT_SET |
Automated Detection
Tool | Version | Checker | Description | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Astrée | |||||||||||||||||||||||||||||
Include Page | Astrée_V | Astrée_V | errno-reset | Partially checked | Axivion Bauhaus Suite | ||||||||||||||||||||||||
Include Page | Axivion Bauhaus Suite_V | Axivion Bauhaus Suite_V | CertC-ERR30 | Fully implemented | Compass/ROSE | Could detect violations of this rule by ensuring that each library function is accompanied by the proper treatment of | 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 | LDRA tool suite |
| 111 D, 121 D, 122 D, 132 D, 134 D | Fully implemented | |||||||||||||||||||||
Parasoft C/C++test Include Page | | Parasoft_V | Parasoft_V | CERT_C-ERR30-a | Properly use errno value | C++test |
| CERT_C-ERR30-a | Properly use errno value | ||||||||||||||||||||
| Checks for:
Rule fully covered. | ||||||||||||||||||||||||||||
Include Page | Polyspace Bug Finder_V | Polyspace Bug Finder_V | errno not reset before calling a function that sets errno errno incorrectly checked for error conditions The value of The value of | PRQA QA-C | Include Page | | PRQA QA-C_v | PRQA QA-C_v | 2500, 2501, 2502, 2503
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 Secure Coding Standard | EXP12-C. Do not ignore values returned by functions | Prior to 2018-01-12: CERT: Unspecified Relationship |
ISO/IEC TS 17961:2013 | Incorrectly setting and using errno [inverrno] | Prior to 2018-01-12: CERT: Unspecified Relationship |
CWE 2.11 | CWE-456, Missing Initialization of a Variable | 2017-07-05: CERT: Rule subset of CWE |
CERT-CWE Mapping Notes
Key here for mapping notes
CWE-456 and ERR30-C
CWE-456 = EXP33-C
CWE-456 = Union( ERR30-C, list) where list =
...
- Reading potentially uninitialized variables besides errno
CWE-248 and ERR30-C
Intersection( CWE-248, ERR30-C) = Ø
CWE-248 is only for languages that support exceptions. It lists C++ and Java, but not C.
Bibliography
[Brainbell.com] | Macros and Miscellaneous Pitfalls |
[Horton 1990] | Section 11, p. 168 Section 14, p. 254 |
[IEEE Std 1003.1-2013] | XSH, System Interfaces, fopen |
[Koenig 1989] | Section 5.4, p. 73 |
[Summit 2005] |
...