CERT.EXIT.HANDLER_TERMINATE

Do not call an exit function from exit handler registered functions.

The CERT.EXIT.HANDLER_TERMINATE checker flags code that calls an exit function from an exit handler function. In addition to calling exit() and quick_exit(), this checker also flags calls to longjmp(), as specified by CERT rule ENV32-C.

Note that this checker will only flags cases where the exit handler and the call that installs it are in the same compilation unit.

Vulnerability and risk

Calling the exit function from an exit handler function that has further called any exit function can lead to a nested call, and a nested call to an exit function is an undefined behavior.

Mitigation and prevention

Ensure all exit handlers return normally.

Vulnerable code example

Copy
    #include <stdlib.h>

    void exit1(void)
    {
        return;
   }

    void exit2(void)
    {
       extern int some_condition;
       if (some_condition) {
           exit(0);
       }
       return;
   }

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

This non-compliant code example flags defect CERT.EXIT.HANDLER_TERMINATE at Line 12 as exit is called from the exit handler function and the exit handler function ‘exit2’ is not returned normally.

Fixed code example

Copy
   #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;
  }

The problem from the previous snippet is fixed. In the compliant example above, both exit handler functions ‘exit1’ and ‘exit2’ are returning normally.