The C99 exit()
function is used for normal program termination. Nested calls to exit()
result in undefined behavior. This can only occur when exit()
is invoked from a function registered with atexit()
, or when exit()
is called from within a signal handler (see SIG30-C. Call only asynchronous-safe functions within signal handlers).
No atexit()
handler should terminate in any way other than by returning. It is important and potentially safety-critical for all the atexit()
handlers to be allowed to perform their cleanup actions. This is particularly true because the main program doesn't always know about handlers that may have been installed by support libraries.
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.
#include <stdio.h> #include <stdlib.h> void exit1(void) { /* ...cleanup code... */ return; } void exit2(void) { if (/* condition */) { /* ...more cleanup code... */ exit(0); } return; } int main(void) { atexit(exit1); atexit(exit2); /* ...program code... */ exit(0); }
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.
#include <stdio.h> #include <stdlib.h> void exit1(void) { /* ...cleanup code... */ return; } void exit2(void) { if (/* condition */) { /* ...more cleanup code... */ } return; } int main(void) { atexit(exit1); atexit(exit2); /* ...program code... */ exit(0); }
Risk Assessment
Multiple calls to exit()
are unlikely, and at worst will only cause denial-of-service attacks or abnormal program termination.
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
[[ISO/IEC 9899:1999]] Section 7.20.4.3, "The exit
function"
[[ISO/IEC PDTR 24772]] "EWD Structured Programming"
10. Environment (ENV) ENV33-C. Do not call the longjmp function to terminate a call to a function registered by atexit()