No atexit()
-registered 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 application programmer does not always know about handlers that may have been installed by support libraries. Two specific issues include nested calls to exit()
and terminating a call to an atexit()
registered handler by invoking longjmp
.
The C99 C exit()
function is used for normal program termination. (See recommendation ERR04-C. Choose an appropriate termination strategy.) Nested calls to exit()
result in undefined behavior. (See also undefined behavior #172 182 in Annex J.) This can occur only occur when exit()
is invoked from a function registered with atexit()
, or when exit()
is called from within a signal handler. (See rule SIG30-C. Call only asynchronous-safe functions within signal handlers.)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#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) {
if (atexit(exit1) != 0) {
/* Handle error */
}
if (atexit(exit2) != 0) {
/* Handle error */
}
/* ...program code... */
exit(0);
}
|
...
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);
}
|
...
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;
}
}
|
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdlib.h>
void exit1(void) {
/* ... */
return;
}
int main(void) {
if (atexit(exit1) != 0) {
/* Handle error */
}
/* ... */
exit(0);
}
|
...
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.
...
Tool | Version | Checker | Description | section|
---|---|---|---|---|
Compass/ROSE |
|
| Section | Can detect violations of this rule. In particular, it ensures that all functions registered with |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
...
CERT C++ Secure Coding Standard: ENV32-CPP. All atexit handlers must return normally
ISO/IEC 9899:19992011 Section 7.22.4.2, "The atexit
function," and Section 7.2022.4.34, "The exit
function"
ISO/IEC TR 24772 "EWD Structured Programmingprogramming" and "REU Termination Strategystrategy"
MITRE CWE: CWE ID 705, "Incorrect Control Flow Scopingcontrol flow scoping"
Bibliography
...