Versions Compared

Key

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

...

Non-Compliant Code Example

In this code as example the main function exits two functions registered with function exit1() is registered by atexit() are called. Given the define statement exitearly=1 the program calls exit within the first function called in the atexit() cycle. The behavior that follows is undefined: some implementations will ignore the second call to exit and just continue calling the atexit functions in the appropriate order. Other implementations will enter an infinite loop with the atexit functions being called repeatedlyso upon program termination exit1() is called and certain cleanup and maintenance functions can occur. If some failure case <expr> evaluates as true though the program attempts to fully exit before the cleanup code can be processed. In these cases where expr evaluates to true exit() will be called twice and the behavior is undefined. Some compilers will simply ignore the exit() call as it in is a function registered by atexit().

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

#define exitearly 1

void exit1(void) {
if(expr)
  puts("Exit second.\n");
}

void exit2(void) {
  puts("Exit first.\n");
  if (exitearly) {
     exit();
       //clean up and ready program for closing
         exit(1);
  }...
}

int main (void) {

  if (expr) {
    atexit(exit1);
    atexit(exit2);...
    exit(1);
  }
  else {
    exit2();
  }

   //program code
     return 0;
}

Compliant Code

To have functionality where the program can quit from within a function registered by at_exit() it is necessary to use a function used for abnormal termination such as _Exit() or abort().

<include _Exit() description>a c99 defined function is described as follows: 

The function _exit terminates the calling process "immediately". Any open file descriptors belonging to the process are closed; any children of the process are inherited by process 1, init, and the process's parent is sent a SIGCHLD signal. The value status is returned to the parent process as the process's exit status, and can be collected using one of the wait family of calls. The function _Exit is equivalent to _exit.

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

#define exitearly 1#include <stdio.h>
#include <stdlib.h>

void exit1(void)
{
  printf("Exit second.\n");
}

void exit2 (void)
{
  printf("Exit first.\n");
  if (exitearly) {
 {
if(expr)
       _Exit();
       //clean up and ready program for closing
         _Exit(1);
  }...
}

int main (void) {

  if (expr) {
    atexit(exit1);
    atexit(exit2);
    exit(1);
  }
  else {
    exit2();
  }

...
     //program code
     return 0;
}

All functions registered by the atexit() function are called, in the reverse order of their registration.

...

The call to _Exit() will immediately terminate the program and no undefined behavior will happen like in the non compliant example.

Risk Assessment

Multiple calls to exit in code are likely to be rare but if exist can cause denial of service and abnormal program termination.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MSC31-C

1 (low)

1 (unlikely)

3(low)

P6

L2

...