GitHub
CERT Secure Coding

ENV32-C. All exit handlers must return normally

The C Standard provides three functions that cause an application to terminate normally: _Exit() , exit() , and quick_exit() . These are collectively called exit functions . When the exit() function is called, or control transfers out of the main() entry point function, functions registered with atexit() are called (but not at_quick_exit() ). 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.

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 .

A nested call to an exit function is undefined behavior . (See undefined behavior 187 .) This behavior can occur only when an exit function is invoked from an exit handler or when an exit function is called from within a signal handler. (See SIG30-C. Call only asynchronous-safe functions within signal handlers .)

If a call to the longjmp() function is made that would terminate the call to a function registered with atexit() , the behavior is undefined behavior 187 .

Noncompliant Code Example

In this noncompliant code example, the exit1() and exit2() functions are registered by atexit() to perform required cleanup upon program termination. However, if some_condition evaluates to true, exit() is called a second time, resulting in undefined behavior 187 .

Non-compliant code
#include <stdlib.h>

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

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

Functions registered by the atexit() function are called in the reverse order from which they were registered. Consequently, 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.

Compliant Solution

A function that is registered as an exit handler by atexit() must exit by returning, as in this compliant solution:

Compliant code
#include <stdlib.h>

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

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

Noncompliant Code Example

In this noncompliant code example, exit1() is registered by atexit() so that upon program termination, exit1() is called. The exit1() function jumps back to main() to return, with undefined results.

Non-compliant code
#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

This compliant solution does not call longjmp() but instead returns from the exit handler normally: ::code-block{quality="good"}``` c #include <stdlib.h>

void exit1(void) { return; }

int main(void) { if (atexit(exit1) != 0) { /* Handle error */ } return 0; }


::

## Risk Assessment

Terminating a call to an exit handler in any way other than by returning is [undefined behavior](/sei-cert-c-coding-standard/back-matter/bb-definitions#BB.Definitions-undefinedbehavior) and may result in [abnormal program termination](/sei-cert-c-coding-standard/back-matter/bb-definitions#BB.Definitions-abnormaltermination) or other unpredictable behavior. It may also prevent other registered handlers from being invoked.

|         |          |            |            |            |          |        |
|---------|----------|------------|------------|------------|----------|--------|
| Rule    | Severity | Likelihood | Detectable | Repairable | Priority | Level  |
| ENV32-C | Medium   | Likely     | Yes        | No         | **P12**  | **L1** |

### Automated Detection

<table class="wrapped"><tbody><tr class="header"><th><p>Tool</p></th><th><p>Version</p></th><th><p>Checker</p></th><th><p>Description</p></th></tr><tr class="odd"><td><a href="/sei-cert-c-coding-standard/back-matter/ee-analyzers/astree">Astrée</a></td><td><div class="content-wrapper">25.10</div></td><td><p><strong>exit-handler-bad-function</strong></p></td><td>Partially checked + soundly supported</td></tr><tr class="even"><td><a href="/sei-cert-c-coding-standard/back-matter/ee-analyzers/axivion-bauhaus-suite">Axivion Bauhaus Suite</a></td><td><div class="content-wrapper"><p>7.2.0</p></div></td><td><strong>CertC-ENV32</strong></td><td><br />
</td></tr><tr class="odd"><td><a href="/sei-cert-c-coding-standard/back-matter/ee-analyzers/codesonar">CodeSonar</a></td><td><div class="content-wrapper">9.1p0</div></td><td><p><strong>BADFUNC.ABORT</strong><br />
<strong>BADFUNC.EXIT</strong><br />
<strong>BADFUNC.LONGJMP</strong></p></td><td><p>Use of abort<br />
Use of exit<br />
Use of longjmp</p></td></tr><tr class="even"><td><a href="/sei-cert-c-coding-standard/back-matter/ee-analyzers/rose">Compass/ROSE</a></td><td><p><br />
</p></td><td><p><br />
</p></td><td><p>Can detect violations of this rule. In particular, it ensures that all functions registered with <code>       atexit()      </code> do not call functions such as <code>       exit()      </code></p></td></tr><tr class="odd"><td style="text-align: left;" style="vertical-align: top"><a href="/sei-cert-c-coding-standard/back-matter/ee-analyzers/cppcheck-premium">Cppcheck Premium</a></td><td style="text-align: left;" style="vertical-align: top"><div class="content-wrapper">24.9.0</div></td><td><strong>premium-cert-env32-c</strong></td><td><p><br />
</p></td></tr><tr class="even"><td><a href="/sei-cert-c-coding-standard/back-matter/ee-analyzers/helix-qac">Helix QAC</a></td><td><div class="content-wrapper"><p>2025.2</p></div></td><td><p><strong>DF4856, DF4857, DF4858</strong></p></td><td><br />
</td></tr><tr class="odd"><td><a href="/sei-cert-c-coding-standard/back-matter/ee-analyzers/klocwork">Klocwork</a></td><td><div class="content-wrapper"><p>2025.2</p></div></td><td><div class="content-wrapper"><strong>CERT.EXIT.HANDLER_TERMINATE</strong></div></td><td><div class="content-wrapper"><p><br />
</p></div></td></tr><tr class="even"><td><a href="/sei-cert-c-coding-standard/back-matter/ee-analyzers/ldra">LDRA tool suite</a></td><td><div class="content-wrapper">9.7.1</div></td><td><strong>122 S<br />
7 S</strong></td><td>Enhanced enforcement</td></tr><tr class="odd"><td><a href="/sei-cert-c-coding-standard/back-matter/ee-analyzers/parasoft">Parasoft C/C++test</a></td><td><div class="content-wrapper"><p>2025.2</p></div></td><td><p><strong>CERT_C-ENV32-a</strong></p></td><td><p>Properly define exit handlers</p></td></tr><tr class="even"><td><p><a href="/sei-cert-c-coding-standard/back-matter/ee-analyzers/polyspace-bug-finder">Polyspace Bug Finder</a></p></td><td><div class="content-wrapper"><p>R2025b</p></div></td><td><a href="https://www.mathworks.com/help/bugfinder/ref/certcruleenv32c.html">CERT C: Rule ENV32-C</a></td><td>Checks for abnormal termination of exit handler (rule fully covered)</td></tr><tr class="odd"><td><a href="/sei-cert-c-coding-standard/back-matter/ee-analyzers/rulechecker">RuleChecker</a></td><td><div class="content-wrapper"><p>25.10</p></div></td><td><p><strong>exit-handler-bad-function</strong></p></td><td>Partially checked</td></tr></tbody></table>

### Related Vulnerabilities

Search for [vulnerabilities](/sei-cert-c-coding-standard/back-matter/bb-definitions#BB.Definitions-vulnerability) resulting from the violation of this rule on the [CERT website](https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+ENV32-C) .

## Related Guidelines

[Key here](/sei-cert-c-coding-standard/front-matter/introduction/how-this-coding-standard-is-organized#HowthisCodingStandardisOrganized-RelatedGuidelines) (explains table format and definitions)

|                                                                                                                      |                                                                                                                                |                                                     |
|----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------|
| Taxonomy                                                                                                             | Taxonomy item                                                                                                                  | Relationship                                        |
| [CERT C Secure Coding Standard](/sei-cert-c-coding-standard/)                                                        | [SIG30-C. Call only asynchronous-safe functions within signal handlers](/sei-cert-c-coding-standard/rules/signals-sig/sig30-c) | Prior to 2018-01-12: CERT: Unspecified Relationship |
| [ISO/IEC TR 24772:2013](/sei-cert-c-coding-standard/back-matter/aa-bibliography#AA.Bibliography-ISO-IECTR24772-2013) | Structured Programming \[EWD\]                                                                                                 | Prior to 2018-01-12: CERT: Unspecified Relationship |
| [ISO/IEC TR 24772:2013](/sei-cert-c-coding-standard/back-matter/aa-bibliography#AA.Bibliography-ISO-IECTR24772-2013) | Termination Strategy \[REU\]                                                                                                   | Prior to 2018-01-12: CERT: Unspecified Relationship |
| [CWE 2.11](https://cwe.mitre.org/data/index.html)                                                                    | [CWE-705](http://cwe.mitre.org/data/definitions/705.html) , Incorrect Control Flow Scoping                                     | 2017-07-10: CERT: Rule subset of CWE                |

## CERT-CWE Mapping Notes

[Key here](/sei-cert-c-coding-standard/front-matter/introduction/how-this-coding-standard-is-organized#HowthisCodingStandardisOrganized-CERT-CWEMappingNotes) for mapping notes

### CWE-705 and ENV32-C

CWE-705 = Union( ENV32-C, list) where list =

  

-   Improper control flow besides a non-returning exit handler

  

  

------------------------------------------------------------------------

<a href="/sei-cert-c-coding-standard/rules/environment-env/env31-c"><img src="/attachments/87152044/88034188.png" /></a> <a href="/sei-cert-c-coding-standard/rules/environment-env/"><img src="/attachments/87152044/88034190.png" /></a> <a href="/sei-cert-c-coding-standard/rules/environment-env/env33-c"><img src="/attachments/87152044/88034189.png" /></a>