You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 69 Next »

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 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.)

TR 24731-1 introduces the new type errno_t that is defined to be type int in errno.h and elsewhere. Many of the functions defined in TR 24731-1 return values of this type. The errno_t type should be used as the type of an object that may only contain 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.

This recommendation depends on TR 24731-1 and advocates using errno_t in new code where appropriate.

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 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 EINVAL; }
  errno = 0;
  if (fgetpos(file, &offset) != 0) { return errno; }
  if (fscanf(file, "%i %i %i", &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;
}

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

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.

#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;
  fpos_t offset;

  if (file == NULL) { return EINVAL; }
  errno = 0;
  if (fgetpos(file, &offset) != 0 ) { return errno; }
  if (fscanf(file, "%i %i %i", &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: EINVAL and EIO are not defined in the C Standard, but they are available in most implementations and are defined in POSIX.

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.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

DCL09-C

low

unlikely

low

P3

L3

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

Bibliography

[ISO/IEC 9899:2011]Section 6.7.6.3, "Function Declarators (including prototypes)"
[Open Group 2004] 

 

  • No labels