Use ferror()
rather than errno
to check whether an error has occurred on a file stream (for example, after a long chain of stdio
calls). The ferror()
function tests the error indicator for a specified stream and returns nonzero if and only if the error indicator is set for the stream.
Many implementations of the stdio
package adjust their behavior slightly if stdout
is a terminal. To make the determination, these implementations perform some operation that fails (with ENOTTY
) if stdout
is not a terminal. Although the output operation goes on to complete successfully, errno
still contains ENOTTY
. This behavior can be mildly confusing, but it is not strictly incorrect because it is meaningful for a program to inspect the contents of errno
only after an error has been reported. More precisely, errno
is meaningful only after a library function that sets errno
on error has returned an error code.
errno = 0; printf("This\n"); printf("is\n"); printf("a\n"); printf("test.\n"); if (errno != 0) { fprintf(stderr, "printf failed: %s\n", strerror(errno)); } |
This compliant solution uses ferror()
to detect an error. In addition, if an early call to printf()
fails, later calls may modify errno
, whether they fail or not, so the program cannot rely on being able to detect the root cause of the original failure if it waits until after a sequence of library calls to check.
printf("This\n"); printf("is\n"); printf("a\n"); printf("test.\n"); if (ferror(stdout)) { fprintf(stderr, "printf failed\n"); } |
Checking errno
after multiple calls to library functions can lead to spurious error reporting, possibly resulting in incorrect program operation.
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ERR01-C | Low | Probable | Low | P6 | L2 |
Tool | Version | Checker | Description |
---|---|---|---|
CC2.ERR01 | Fully implemented | ||
LDRA tool suite | 44 S | Enhanced Enforcement | |
Parasoft C/C++test | CERT_C-ERR01-a | The error indicator 'errno' shall not be used |
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
SEI CERT C++ Coding Standard | VOID ERR01-CPP. Use ferror() rather than errno to check for FILE stream errors |
[Horton 1990] | Section 14, p. 254 |
[Koenig 1989] | Section 5.4, p. 73 |