All 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. In addition to the C standard library functions mentioned in ERR33-C. Detect and handle standard library errors, the following functions defined in POSIX require error checking (list is not all-inclusive).
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 to the same column.
Function | Successful Return | Error Return |
|
---|---|---|---|
| Pointer to a |
|
|
| Pointer to a |
|
|
|
| Nonzero | Unchanged |
Setting errno
is a POSIX [ISO/IEC 9945:2008] extension to the C Standard. On error, posix_memalign()
returns a value that corresponds to one of the constants defined in the <errno.h>
header. The function does not set errno
. The posix_memalign()
function is optional and is not required to be provided by POSIX-conforming implementations.
Noncompliant Code Example (POSIX)
In this noncompliant code example, fmemopen()
and open_memstream()
are assumed to succeed. However, if the calls fail, the two file pointers in
and out
will be null and the program will have undefined behavior.
#include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { FILE *out; FILE *in; size_t size; char *ptr; if (argc != 2) { /* Handle error */ } in = fmemopen(argv[1], strlen(argv[1]), "r"); /* Use in */ out = open_memstream(&ptr, &size); /* Use out */ return 0; }
Compliant Solution (POSIX)
A compliant solution avoids assuming that fmemopen()
and open_memstream()
succeed regardless of its arguments and tests the return value of the function before using the file pointers in
and out
:
#include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { FILE *out; FILE *in; size_t size; char *ptr; if (argc != 2) { /* Handle error */ } in = fmemopen(argv[1], strlen(argv[1]), "r"); if (in == NULL){ /* Handle error */ } /* Use in */ out = open_memstream(&ptr, &size); if (out == NULL){ /* Handle error */ } /* Use out */ return 0; }
Exceptions
ERR33-C-EX1: The exception from EXP12-C. Do not ignore values returned by functions still applies. If the return value is inconsequential or if any errors can be safely ignored, such as for functions called because of their side effects, the function should be explicitly cast to void
to signify programmer intent.
ERR33-C-EX2: Ignore the return value of a function that cannot fail or whose return value cannot signify that an error condition need not be diagnosed. For example, strcpy()
is one such function.
Return values from the following functions do not need to be checked because their historical use has overwhelmingly omitted error checking, and the consequences are not relevant to security.
Function | Successful Return | Error Return |
---|---|---|
| Number of characters (nonnegative) | Negative |
| Character written |
|
| Nonnegative |
|
| Wide character written |
|
| Number of characters (nonnegative) | Negative |
| Number of wide characters (nonnegative) | Negative |
| Number of wide characters (nonnegative) | Negative |
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 |
---|---|---|---|---|---|
POS54-C | High | Likely | Medium | P18 | L1 |
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
CodeSonar | 8.1p0 | LANG.FUNCS.IRV | Ignored return value |
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 | ||
2017.07 | CHECKED_RETURN | Finds inconsistencies in how function call return values are handled. Coverity Prevent cannot discover all violations of this recommendation, so further verification is necessary | |
Klocwork | 2024.3 | SV.RVT.RETVAL_NOTTESTED | |
LDRA tool suite | 9.7.1 | 80 D | Partially implemented |
Parasoft C/C++test | 2023.1 | CERT_C-POS54-a | The value returned by a function having non-void return type shall be used |
R2024a | Returned value of a sensitive function not checked | Sensitive functions called without checking for unexpected return values and errors | |
PRQA QA-C | Unable to render {include} The included page could not be found. | 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 NULL
, Flash writes to an offset from the return value. Dereferencing NULL
usually results in a program crash, but dereferencing an offset from NULL
allows an exploit to succeed without crashing the program.
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Key here (explains table format and definitions)
Bibliography
[DHS 2006] | Handle All Errors Safely |
[Henricson 1997] | Recommendation 12.1, "Check for All Errors Reported from Functions" |
[ISO/IEC 9899:2011] | Subclause 7.21.7.10, "The ungetc Function" |