The C99 exit()
function is used for normal program termination. Nested calls to exit()
result in undefined behavior. This most frequently occurs when multiple functions are registered with atexit()
.
Non-Compliant Code Example
So that it might perform cleanup upon program termination, exit1()
is registered by atexit()
. If <expr>
evaluates to true, exit()
will be called a second time, resulting in undefined behavior.
#include <stdio.h> #include <stdlib.h> void exit1(void) { if (/* condition */) { /* ...cleanup code... */ exit(0); } } int main (void) { atexit(exit1); /* ...program code... */ exit(0); }
Compliant Solution
_Exit()
and abort()
will both immediately halt program execution, and may be used within functions registered by atexit()
.
According to C99, [[ISO/IEC 9899-1999]]:
The
_Exit
function causes normal program termination to occur and control to be returned to the host environment. No functions registered by theatexit
function or signal handlers registered by thesignal
function are called. The status returned to the host environment is determined in the same way as for theexit
function. Whether open streams with unwritten buffered data are flushed, open streams are closed, or temporary files are removed is implementation-defined. The_Exit
function cannot return to its caller.
#include <stdio.h> #include <stdlib.h> void exit1(void) { if (/* condition */) { /* ...cleanup code... */ _Exit(0); } } int main (void) { atexit(exit1); /* ...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 |
1 (low) |
1 (unlikely) |
3 (low) |
P3 |
L3 |
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"
11. Environment (ENV) ENV33-C. Do not call the longjmp function to terminate a call to a function registered by atexit()