...
If a call to the longjmp
function is made that would terminate the call to a function registered with atexit()
, the behavior is undefined.
Non-Compliant Code Example
In this non-compliant code example, the exit1()
and exit2()
functions are registered by atexit()
to perform required cleanup upon program termination. However, if condition
evaluates to true, exit()
is called a second time, resulting in undefined behavior.
...
Because all functions registered by the atexit()
function are called in the reverse order of their registration, if exit2()
exits in any way other than by returning, exit1()
will not be executed. This may also be true for atexit()
handlers installed by support libraries.
Compliant Solution
A function that is registered as an exit handler by atexit()
must exit by returning, and not in any other manner.
Code Block | ||
---|---|---|
| ||
#include <stdio.h> #include <stdlib.h> void exit1(void) { /* ...cleanup code... */ return; } void exit2(void) { if (/* condition */) { /* ...more cleanup code... */ } return; } int main(void) { if (atexit(exit1) != 0) { /* Handle Error */ } if (atexit(exit2) != 0) { /* Handle Error */ } /* ...program code... */ exit(0); } |
Non-Compliant Code Example
The function exit1()
is registered by atexit()
, so upon program termination, exit1()
is called. Execution will jump back to main()
and return, with undefined results.
Code Block | ||
---|---|---|
| ||
#include <stdio.h> #include <stdlib.h> #include <setjmp.h> jmp_buf env; int val; void exit1(void) { /* ... */ longjmp(env, 1); } int main(void) { if (atexit(exit1) != 0) { /* handle error */ } /* ... */ if (setjmp(env) == 0) { exit(0); } else { return 0; } } |
Compliant Code
Careful thought about program flow is the best prevention for an invalid call to longjmp()
. After the exit
function has been called, avoid using longjmp()
where it will cause a function to terminate.
Code Block | ||
---|---|---|
| ||
#include <stdlib.h> void exit1(void) { /* ... */ return; } int main(void) { if (atexit(exit1) != 0) { /* handle error */ } /* ... */ exit(0); } |
Risk Assessment
Terminating a call to an atexit()
registered handler in any way other than by returning results in undefined behavior , and may result in abnormal program termination or other unpredictable behavior. It may also prevent other registered handlers from being invoked.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ENV32-C | medium | likely | medium | P12 | L1 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Wiki Markup |
---|
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section 7.20.4.3, "The {{exit}} function" \[[ISO/IEC PDTR 24772|AA. C References#ISO/IEC PDTR 24772]\] "EWD Structured Programming" and "REU Termination Strategy" |
...