Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Avoid in-band error indicators while designing interfaces. This practice is commonly used by C library functions but is not recommended. One example from the C standard of a troublesome in-band error indicator is EOF (see FIO34-C. Use int to capture the return value of character IO functions and FIO35-C. Use feof() and ferror() to detect end-of-file and file errors when sizeof(int) == sizeof(char)). Another problematic use of in-band error indicators from the C standard involving the size_t and time_t types is described by MSC31-C. Ensure that return values are compared against the proper type.

...

This specific noncompliant code example is from the Linux Kernel Mailing List archive site at http://lkml.org/, although similar examples are common.

Code Block
bgColor#FFCCCC
int i;
ssize_t count = 0;

for (i = 0; i < 9; ++i) {
  count += sprintf(
    sprintf(buf + count, "%02x ", ((u8 *)&slreg_num)[i]
  );
}
count += sprintf(buf + count, "\n");

...

Code Block
bgColor#ccccff
int i;
rsize_t count = 0;
errno_t err;

for (i = 0; i < 9; ++i) {
  err = sprintf_m(
    buf + count, "%02x ", &count,
                        ((u8 *)&slreg_num)[i]
  );
  if (err != 0) {
    /* handleHandle print error */
  }
}
err = sprintf_m(
  buf + count, "%02x ", &count,
                      ((u8 *)&slreg_num)[i]
);
if (err != 0) {
  /* handleHandle print error */
}

Exceptions

ERR02-EX1: Null pointers are another example of an in-band error indicator. Use of null pointers is not quite as bad because it is supported by the language. According to C99 Section 6.3.2.3, "Pointers":

If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.

ERR02-EX2: One You may use a function returning in-band error indicators if one you can securely guarantee the program will not try to continue processing should an error occur in the function.

For example, the functions defined in TR24731-1 provide hooks for internal constraint violations. If a constraint violation handler is guaranteed not to return upon an error occurring, then one you may safely ignore errors returned by these functions. One You might accomplish this by having the constraint-violation handler call abort(), or longjmp(), for instance.

...

Noncompliant Code Example (TR24731-1)

In this noncompliant code example, the error handler returns normally, while the strcpy_s() function's return value is not checked.

Code Block
bgColor#FFCCCC
constraint_handler_t handle_errors(void) {
  constraint_handler_t data;
  /* define what to do when error occurs */
  return data;
}

/*...*/

set_constraint_handler(handle_errors);

/*...*/

/* Returns zero on success */
errno_t function(char *dst1){
  char src1[100] = "hello";

  strcpy_s(dst1, sizeof(dst1), src1);
  /* At this point strcpy_s may have yielded an
     error and handle_errors() might have returned */

  /* ... */
  return 0;
}

Compliant

...

Solution (TR24731-1)

Here the code is rectified by having the In this compliant solution, the error handler terminate terminates the program, which ensures ensuring that strcpy_s() never returns unless it worked perfectlyfully succeeds.

Code Block
bgColor#CCCCFF
/*
 * The abort_handler_s() function writes a message on the
 * standard error stream and then calls the abort() function.
 */
set_constraint_handler(abort_handler_s);

/*...*/

/* Returns zero on success */
errno_t function(char *dst1){
  char src1[100] = "hello";

  strcpy_s(dst1, sizeof(dst1), src1);
  /* Because abort_handler_s() never returns,
     we only get here if strcpy_s() succeeds. */

  /* ... */
  return 0;
}

Risk Analysis

The risk of in using in-band error indicators is difficult to quantify and is consequently given as low. However, if the use of in-band error indicators results in programmers' failing to check status codes or incorrectly checking them, the consequences can be more severe.

...