Many existing functions that return an errno
are declared as returning a value of type int
. It is semantically unclear by looking at the function declaration or prototype if these functions return an error status or a value (or worse, some combination of the two).
TR 24731-1 defines a new type of errno_t
that is type int
in <errno.h>
and elsewhere. Many of the functions defined in TR 24731-1 return values of this type. As a matter of programming style, errno_t
should be used as the type of something that deals only with the values that might be found in errno
. For example, a function that returns the value of errno
should be declared as having the return type errno_t
.
Non-Compliant Code Example
This non-compliant code example illustrates a function called opener()
that 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
. Consequently, the meaning of the return value is not as clear as it could be.
enum { NO_FILE_POS_VALUES = 3 }; int opener(FILE* file, int *width, int *height, int *data_offset) { int file_w; int file_h; int file_o; fpos_t offset; if (file == NULL) { return -1; } if (fgetpos(file, &offset) != 0) { return -1; } if (fscanf(file, "%i %i %i", &file_w, &file_h, &file_o) != NO_FILE_POS_VALUES) { return -1; } if (fsetpos(file, &offset) != 0) { return -1; } *width = file_w; *height = file_h; *data_offset = file_o; return 0; }
Compliant Solution
In this compliant solution, the opener()
function returns a value of type errno_t
, providing a clear indication that this returns a value that might be found in errno
.
#include <errno.h> enum { NO_FILE_POS_VALUES = 3 }; errno_t opener(FILE* file, int *width, int *height, int *data_offset) { int file_w; int file_h; int file_o; int rc; fpos_t offset; if (file == NULL) { return EINVAL; } if ((rc = fgetpos(file, &offset)) != 0 ) { return rc; } if (fscanf(file, "%i %i %i", &file_w, &file_h, &file_o) != NO_FILE_POS_VALUES) { return EIO; } if ((rc = fsetpos(file, &offset)) != 0 ) { return rc; } *width = file_w; *height = file_h; *data_offset = file_o; return 0; }
NOTE: EINVAL
and EIO
are not defined in C99, but they are defined in most implementations.
Risk Assessment
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 will help mitigate it.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
DCL09-A |
1 (low) |
1 (unlikely) |
2 (medium) |
P2 |
L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[ISO/IEC TR 24731-1-2007]]
[[ISO/IEC 9899-1999]] Section 6.7.5.3, "Function declarators (including prototypes)"