Versions Compared

Key

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

...

  • A return value (especially of type errno_t)
  • An argument passed by address
  • A global object (e.g., such as errno)
  • longjmp()
  • Some combination of the above

...

Code Block
bgColor#ffcccc
langc
void g(void) {
  /* ... */
  if (something_really_bad_happens) {
    fprintf(stderr, "Something really bad happened!\n");
    abort();
  }
  /* ... */
}

void f(void) {
  g();
  /* ... doDo the rest of f ... */
}

If something_really_bad_happens in g(), the function prints an error message to stderr and then calls abort(). The problem is that this application-independent code does not know the context in which it is being called, so it is erroneous to handle the error.

...

Code Block
bgColor#ccccff
langc
const errno_t ESOMETHINGREALLYBAD = 1;

errno_t g(void) {
  /* ... */
  if (something_really_bad_happens) {
    return ESOMETHINGREALLYBAD;
  }
  /* ... */
  return 0;
}

errno_t f(void) {
  errno_t status = g();
  if (status != 0) {
    return status;
  }

  /* ... doDo the rest of f ... */

  return 0;
}

...

Code Block
bgColor#ccccff
langc
const errno_t ESOMETHINGREALLYBAD = 1;

void g(errno_t * err) {
  if (err == NULL) {
    /* Handle null pointer */
  }
  /* ... */
  if (something_really_bad_happens) {
    *err = ESOMETHINGREALLYBAD;
  } else {
    /* ... */
    *err = 0;
  }
}

void f(errno_t * err) {
  if (err == NULL) {
    /* Handle null pointer */
  }
  g(err);
  if (*err == 0) {
    /* ... doDo the rest of f ... */
  }
  return 0;
}

...

  • A return status can be returned only if the caller provides a valid pointer to an object of type errno_t. If this argument is NULL, there is no way to indicate this error.
  • Source code becomes even larger because of the possibilities of receiving a null pointer.
  • All error indicators must be checked after calling functions.
  • Any function that allocates resources must ensure they are freed in cases where errors occur.
  • Unlike return values, static analysis tools generally do not diagnose a failure to check error indicators passed as argument pointers.

...

Code Block
bgColor#ccccff
langc
errno_t my_errno; /* alsoAlso declared in a .h file */
const errno_t ESOMETHINGREALLYBAD = 1;

void g(void) {
  /* ... */
  if (something_really_bad_happens) {
    my_errno = ESOMETHINGREALLYBAD;
    return;
  }
  /* ... */
}

void f(void) {
  my_errno = 0;
  g();
  if (my_errno != 0) {
    return;
  }
  /* ... doDo the rest of f ... */
}

The call to f() provides a status indicator that is 0 upon success and a nonzero value upon failure.

...

Code Block
bgColor#ccccff
langc
#include <setjmp.h>

const errno_t ESOMETHINGREALLYBAD = 1;

jmp_buf exception_env;

void g(void) {
  /* ... */
  if (something_really_bad_happens) {
    longjmp(exception_env, ESOMETHINGREALLYBAD);
  }
  /* ... */
}

void f(void) {
  g();
  /* ... doDo the rest of f ... */
}

/* ... */
if (setjmp(exception_env) != 0) {
  /*
   * If we get here, an error occurred; 
   * do not continue processing.
   */
}
/* ... */
f();
/* If we get here, no errors occurred */
/* ... */

...

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

ERR05-C

mediumMedium

probableProbable

highHigh

P4

L3

Automated Detection

Tool

Version

Checker

Description

Compass/ROSE

 

 

Could detect violations of this rule merely by reporting functions that call abort(), exit(), or _Exit() inside an if or switch statement. This would also catch many false positives, as ROSE could not distinguish a library function from an application function

...