| Warning | ||
|---|---|---|
| ||
This section is under construction. |
Many existing functions that return 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.)
...
This recommendation depends on C11 Annex K being implemented and advocates using errno_t in new code where appropriate. 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 noncompliant code example shows a function called opener() that returns errno error codes. However, the function is declared as returning 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,
intsize_t *height,
intsize_t *data_offset
) {
intsize_t file_w;
intsize_t file_h;
intsize_t file_o;
fpos_t offset;
if (file == NULL) { return EINVAL; }
errno = 0;
if (fgetpos(file, &offset) != 0) { return errno; }
if (fscanf(file, "%i%zu %i%zu %i%zu", &file_w, &file_h, &file_o)
!= NO_FILE_POS_VALUES) {
return EIO-1;
}
errno = 0;
if (fsetpos(file, &offset) != 0) { return errno; }
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. Set errno to zero before calling a library function known to set errno, and check errno only after the function returns a value indicating failure.
Compliant Solution (POSIX)
In this compliant solution, the opener() function returns a value of type errno_t, providing a clear indication that this function returns an error code:
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <errno.h>
#include <stdio.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;
fpos_t offset;
if (fileNULL == NULLfile) { return EINVAL; }
errno = 0;
if (fgetpos(file, &offset) != 0 ) { return errno; }
if (fscanf(file, "%i%zu %i%zu %i%zu", &file_w, &file_h, &file_o)
!= NO_FILE_POS_VALUES) {
return EIO;
}
errno = 0;
if (fsetpos(file, &offset) != 0 ) { return errno; }
if (width != NULL) { *width = file_w; }
if (height != NULL) { *height = file_h; }
if (data_offset != NULL) { *data_offset = file_o; }
return 0;
}
|
NOTE: This compliant solution is categorized as a POSIX solution because it returns EINVAL and , which are not defined in defined by POSIX but not by the C Standard, but they are available in most implementations and are defined in POSIX.EIO
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 may reduce errors caused by programmers' misunderstanding the purpose of a return value.
...
Bibliography
...