CERT.STDLIB.SIGNAL

Returning from a computational exception signal handler for SIGFPE, SIGBUS, SIGSEGV, SIGILL, SIGEMT, or SIGTRAP results in undefined behavior.

The CERT.STDLIB.SIGNAL checker flags returns from a computational exception signal handler for SIGFPE, SIGBUS, SIGSEGV, SIGILL, SIGEMT, and SIGTRAP. This checker flags all calls to signal() with any of the specified signal types as being a defect. Therefore, this defect should be interpreted as meaning that the line of code should be reviewed, not that it is necessarily always a defect.

Vulnerability and risk

The behavior is undefined if the program returns from the computational exception signal handler.

Mitigation and prevention

Do not return from the signal handler if the signal is the result of a computational error such as SIGFPE, SIGBUS, SIGSEGV, SIGILL, SIGEMT or SIGTRAP.

Vulnerable code example

Copy
     #include <errno.h>
     #include <limits.h>
     #include <signal.h>
     #include <stdlib.h>

     volatile sig_atomic_t denom;

     void sighandle(int s)
     {
        if (denom == 0) {
            denom = 1;
        }
    }

    int main(int argc, char *argv[])
    {
        if (argc < 2) {
            return 0;
        }

        char *end = NULL;
        long temp = strtol(argv[1], &end, 10);

        if (end == argv[1] || 0 != *end ||
            ((LONG_MIN == temp || LONG_MAX == temp) && errno == ERANGE)) {
            /* Handle error */
        }

        denom = (sig_atomic_t)temp;

        signal(SIGFPE, sighandle);  

        long result = 100 / (long)denom;
        return 0;
    }

In this noncompliant example, Klocwork reports a CERT.STDLIB.SIGNAL defect on Line 31, because the program is returning from the computational signal handler and the behavior is undefined. This noncompliant code example will loop infinitely if given the input 0 and the above program does not behave as expected even after using the signal handler (with signal SIGFPE) to fix the error condition.

Fixed code example

Copy
     #include <errno.h>
     #include <limits.h>
     #include <signal.h>
     #include <stdlib.h>

     int main(int argc, char *argv[]) {
       if (argc < 2) {
         return 0;
       }

      char *end = NULL;
      long denom = strtol(argv[1], &end, 10);

      if (end == argv[1] || 0 != *end ||
          ((LONG_MIN == denom || LONG_MAX == denom) && errno == ERANGE)) {
        /* Handle error */
      }

      long result = 100 / denom;
      return 0;
    }

The above code is compliant because the program is not returning from the SIGFPE handler and instead is invoking the abort (), quick_exit(), or Exit function.

Related checkers

  • MISRA.STDLIB.SIGNAL