When developing new code, declare functions that return errno
with a return type of errno_t
. Many existing functions that return an errno
are declared as returning a value of type int
. It is semantically unclear by looking at inspecting the function declaration or prototype if these functions return an error status or a value ( or, worse, some combination of the two). . (See ERR02-C. Avoid in-band error indicators.)
C11 Annex K introduced the new type TR 24731-1 defines a new type of errno_t
which that is defined to be type int
in <errnoerrno.h>h
and elsewhere. Many of the functions defined in TR 24731-1 C11 Annex K return values of this type. As a matter of programming style, The errno_t
type should be used as the type of something an object that deals may contain only with the values that might be found in errno
. For example, a function which that returns the value of errno
should be declared as having the return type errno_t
.
...
This recommendation depends on C11 Annex K being implemented. The following code can be added to remove this dependency:
Code Block | ||
---|---|---|
| ||
#ifndef __STDC_LIB_EXT1__
typedef int errno_t;
#endif |
Noncompliant Code Example
This non-compliant noncompliant code example illustrates shows a function called opener()
that returns errno
error codes. However, the function is declared as returning a value of type int
. The function, however, uses this return value to indicate the return status of the function by returning values of errno
. an int
. Consequently, the meaning of the return value is not as clear as it could bereadily apparent.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <errno.h> #include <stdio.h> enum { NO_FILE_POS_VALUES = 3 }; int opener( FILE * file, intsize_t *width, int size_t *height, int size_t *data_offset ) { intsize_t file_w; intsize_t file_h; intsize_t file_o; int offsetfpos_t offset; if (file == NULL) { return EINVAL; } errno = 0; if (fgetpos(file, &offset) =!= NULL0) { return -1errno; } if (fscanf(file, "%i%zu %i%zu %i%zu", &file_w, &file_h, &file_o) != 3NO_FILE_POS_VALUES) { return -1; } errno = 0; if (fsetpos(file, &offset) != 0) { return -1errno; } if (width != NULL) { *width = file_w; } if (height != NULL) { *height = file_h; } if (data_offset != NULL) { *data_offset = file_o; } return 0; } |
This noncompliant code example nevertheless complies with ERR30-C. Take care when reading errno.
Compliant Solution (POSIX)
In this compliant solution, the opener()
function returns a value of type errno_t
, providing a clear indication that this returns a values that might be found in errno
.function returns an error code:
Code Block | ||||
---|---|---|---|---|
| ||||
#define __STDC_WANT_LIB_EXT1__ 1 #include <errno.h> #include <stdio.h> #include <stdlib.h> enum { NO_FILE_POS_VALUES = 3 }; errno_t opener( FILE * file, intsize_t *width, intsize_t *height, intsize_t *data_offset ) { intsize_t file_w; intsize_t file_h; intsize_t file_o; int rc; fpos_t offset; if (fileNULL == NULLfile) { return EINVAL; } rcerrno = 0; if (fgetpos(file, &offset); if (rc != 0 ) { return (errno_t)rc; } if (fscanf(file, "%i%zu %i%zu %i%zu", &file_w, &file_h, &file_o) != 3NO_FILE_POS_VALUES) { return EIO; } rcerrno = 0; if (fsetpos(file, &offset); if (rc != 0 ) { return -1errno; } if (width != NULL) { *width = file_w; } if (height != NULL) { *height = file_h; } if (data_offset != NULL) { *data_offset = file_o; } return 0; } |
This compliant solution is categorized as a POSIX solution because it returns EINVAL and
, which are defined by POSIX (IEEE Std 1003.1, 2013 Edition) but not by the C Standard.EIO
Risk Assessment
The misuse of fsetpos()
could move a file stream read to a undesired location in the file. If this location held input from user the user would then gain control of the variables being read from the file.
Failing to test for error conditions can lead to vulnerabilities of varying severity. Declaring functions that return an errno
with a return type of errno_t
will not eliminate this problem but may reduce errors caused by programmers' misunderstanding the purpose of a return value.
Recommendation |
---|
Severity | Likelihood | Remediation Cost | Priority | Level | |
---|---|---|---|---|---|
DCL09- |
1 (low)
1 (low)
2 (medium)
P2
L3
References
C | Low | Unlikely | Low | P3 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Axivion Bauhaus Suite |
| CertC-DCL09 | |||||||
LDRA tool suite |
| 634 S | Partially Implemented |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
SEI CERT C++ Coding Standard | VOID DCL09-CPP. Declare functions that return errno with a return type of errno_t |
ISO/IEC TR 24772:2013 | Ignored Error Status and Unhandled Exceptions [OYB] |
Bibliography
...
\[[ISO/IEC TR 24731-2006|AA. C References#ISO/IEC TR 24731-2006]\]
\[[ISO/IEC 9899-1999:TC2|AA. C References#ISO/IEC 9899-1999TC2]\] Section 6.7.5.3, "Function declarators (including prototypes)" Wiki Markup