Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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 C exit() function is used for normal program termination. (See ERR04-C. Choose an appropriate termination strategy.) Nested calls to exit() result in undefined behavior. (See also undefined behavior 182 in Annex J.) This behavior can occur only 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.)

...

Code Block
bgColor#FFcccc
langc
#include <stdlib.h>

void exit1(void) {
  /* ...cleanup Cleanup code ... */
  return;
}
 
void exit2(void) {
  extern int some_condition;
  if (some_condition) {
    /* ...more More cleanup code ... */
    exit(0);
  }
  return;
}

int main(void) {
  if (atexit(exit1) != 0) {
    /* Handle error */
  }
  if (atexit(exit2) != 0) {
    /* Handle error */
  }
  /* ...program Program code ... */
  return 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 The same may also be true for atexit() handlers installed by support libraries.

...

Code Block
bgColor#ccccFF
langc
#include <stdlib.h>

void exit1(void) {
  /* ...cleanup Cleanup code ... */
  return;
}
 
void exit2(void) {
  extern int some_condition;
  if (some_condition) {
    /* ...more More cleanup code ... */
  }
  return;
}

int main(void) {
  if (atexit(exit1) != 0) {
    /* Handle error */
  }
  if (atexit(exit2) != 0) {
    /* Handle error */
  }
  /* ...program Program code ... */
  return 0;
}

Noncompliant Code Example

...

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

mediumMedium

likelyLikely

mediumMedium

P12

L1

Automated Detection

Tool

Version

Checker

Description

Compass/ROSE

 

 

Can detect violations of this rule. In particular, it ensures that all functions registered with atexit() do not call functions such as exit()

...

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

CERT C++ Secure Coding StandardENV32-CPP. All atexit handlers must return normally
ISO/IEC TR 24772:2013Structured Programming [EWD]
Termination Strategy [REU]
MITRE CWECWE-705, Incorrect control flow scoping

...