The C standard provides three functions which cause an application to terminate normally: _Exit()
, exit()
and quick_exit()
. (See ERR04-C. Choose an appropriate termination strategy.) These are collectively called exit functions. When the exit()
function is called, or control transfers out of the main()
entrypoint entry point function, functions registered with atexit()
are called. When the quick_exit()
function is called, functions registered with at_quick_exit()
(but not atexit()
) are called. These functions are collectively called exit handlers. When the _Exit()
function is called, no exit handlers or signal handlers are called.
No exit handler should terminate in any way other than Exit handlers must terminate by returning. It is important and potentially safety-critical for all exit handlers to be allowed to perform their cleanup actions. This is particularly true because the application programmer does not always know about handlers that may have been installed by support libraries. Two specific issues include nested calls to an exit function and terminating a call to an exit handler by invoking longjmp
.
...
Because all functions registered by the atexit()
function are called in the reverse order of their registrationfrom which they were registered, if exit2()
exits in any way other than by returning, exit1()
will not be executed. The same may also be true for atexit()
handlers installed by support libraries.
...
Noncompliant Code Example
The function In this noncompliant code example, exit1()
is registered by atexit()
, so that upon program termination, exit1()
is called. Execution will jump The exit1()
functions jumps back to main()
and to return, with undefined results.
Code Block | ||||
---|---|---|---|---|
| ||||
#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 Solution
Careful thought about program flow is the The best prevention for an invalid call to longjmp()
. After the exit
function has been called, avoid call
is to carefully consider program flow. Avoid using longjmp()
after a call to an exit function where it will might cause a function program to terminate.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdlib.h> void exit1(void) { return; } int main(void) { if (atexit(exit1) != 0) { /* Handle error */ } return 0; } |
...
CERT C Secure Coding Standard | ERR04-C. Choose an appropriate termination strategy SIG30-C. Call only asynchronous-safe functions within signal handlers |
CERT C++ Secure Coding Standard | ENV32-CPP. All atexit handlers must return normally |
ISO/IEC TR 24772:2013 | Structured Programming [EWD] Termination Strategy [REU] |
MITRE CWE | CWE-705, Incorrect control flow scoping |
...