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