...
- 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 | ||||
|---|---|---|---|---|
| ||||
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 | ||||
|---|---|---|---|---|
| ||||
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 | ||||
|---|---|---|---|---|
| ||||
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 isNULL, 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 | ||||
|---|---|---|---|---|
| ||||
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 | ||||
|---|---|---|---|---|
| ||||
#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 |
|---|---|---|---|
|
| Could detect violations of this rule merely by reporting functions that call |
...