# SIG35-C: Do not return from a computational exception signal handler

This query implements the CERT-C rule SIG35-C:

> Do not return from a computational exception signal handler


## Description

According to the C Standard, 7.14.1.1 \[[ISO/IEC 9899:2011](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-ISO-IEC9899-2011)\], if a signal handler returns when it has been entered as a result of a computational exception (that is, with the value of its argument of `SIGFPE`, `SIGILL`, `SIGSEGV`, or any other implementation-defined value corresponding to such an exception) returns, then the behavior is [undefined](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior). (See [undefined behavior 130](https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-130).)

The Portable Operating System Interface (POSIX<sup>®</sup>), Base Specifications, Issue 7 \[[IEEE Std 1003.1:2013](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-IEEEStd1003.1-2013)\], adds `SIGBUS` to the list of computational exception signal handlers:

> The behavior of a process is undefined after it returns normally from a signal-catching function for a `SIGBUS`, `SIGFPE`, `SIGILL`, or `SIGSEGV` signal that was not generated by `kill()`, `sigqueue()`, or `raise()`.


Do not return from `SIGFPE`, `SIGILL`, `SIGSEGV`, or any other implementation-defined value corresponding to a computational exception, such as `SIGBUS` on POSIX systems, regardless of how the signal was generated.

## Noncompliant Code Example

In this noncompliant code example, the division operation has undefined behavior if `denom` equals `0.` (See [INT33-C. Ensure that division and remainder operations do not result in divide-by-zero errors](https://wiki.sei.cmu.edu/confluence/display/c/INT33-C.+Ensure+that+division+and+remainder+operations+do+not+result+in+divide-by-zero+errors)) and may result in a `SIGFPE` signal to the program.)

```cpp
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>

volatile sig_atomic_t denom;

void sighandle(int s) {
  /* Fix the offending volatile */
  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;
}

```
When compiled with some implementations, this noncompliant code example will loop infinitely if given the input `0`. It illustrates that even when a `SIGFPE` handler attempts to fix the error condition while obeying all other rules of signal handling, the program still does not behave as expected.

## Compliant Solution

The only portably safe way to leave a `SIGFPE`, `SIGILL`, or `SIGSEGV` handler is to invoke `abort()`, `quick_exit()`, or `_Exit()`. In the case of `SIGFPE`, the default action is [abnormal termination](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-abnormaltermination), so no user-defined handler is required:

```cpp
#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;
}
```
**Implementation Details**

Some implementations define useful behavior for programs that return from one or more of these signal handlers. For example, Solaris provides the `sigfpe()` function specifically to set a `SIGFPE` handler that a program may safely return from. [Oracle](http://docs.oracle.com/) also provides platform-specific computational exceptions for the `SIGTRAP`, `SIGBUS`, and `SIGEMT` signals. Finally, GNU libsigsegv takes advantage of the ability to return from a `SIGSEGV` handler to implement page-level memory management in user mode.

## Risk Assessment

Returning from a computational exception signal handler is [undefined behavior](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior).

<table> <tbody> <tr> <th> Rule </th> <th> Severity </th> <th> Likelihood </th> <th> Remediation Cost </th> <th> Priority </th> <th> Level </th> </tr> <tr> <td> SIG35-C </td> <td> Low </td> <td> Unlikely </td> <td> High </td> <td> <strong>P1</strong> </td> <td> <strong>L3</strong> </td> </tr> </tbody> </table>


## Automated Detection

<table> <tbody> <tr> <th> Tool </th> <th> Version </th> <th> Checker </th> <th> Description </th> </tr> <tr> <td> <a> Axivion Bauhaus Suite </a> </td> <td> 7.2.0 </td> <td> <strong>CertC-SIG35</strong> </td> <td> </td> </tr> <tr> <td> <a> CodeSonar </a> </td> <td> 7.2p0 </td> <td> <strong>LANG.STRUCT.RFCESH</strong> </td> <td> Return from Computational Exception Signal Handler </td> </tr> <tr> <td> <a> Helix QAC </a> </td> <td> 2022.4 </td> <td> <strong>DF4846, DF4847, DF4848</strong> </td> <td> </td> </tr> <tr> <td> <a> Klocwork </a> </td> <td> 2022.4 </td> <td> <strong>CERT.STDLIB.SIGNAL</strong> </td> <td> </td> </tr> <tr> <td> <a> LDRA tool suite </a> </td> <td> 9.7.1 </td> <td> <strong>44 S</strong> </td> <td> Enhanced enforcement </td> </tr> <tr> <td> <a> Parasoft C/C++test </a> </td> <td> 2022.2 </td> <td> <strong>CERT_C-SIG35-a</strong> </td> <td> Do not return from a computational exception signal handler </td> </tr> <tr> <td> <a> PC-lint Plus </a> </td> <td> 1.4 </td> <td> <strong>2671, 2764</strong> </td> <td> Fully supported </td> </tr> <tr> <td> <a> Polyspace Bug Finder </a> </td> <td> R2022b </td> <td> <a> CERT C: Rule SIG35-C </a> </td> <td> Checks for return from computational exception signal handler (rule fully covered) </td> </tr> </tbody> </table>


## Related Vulnerabilities

Search for [vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/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+SIG35-C).

## Bibliography

<table> <tbody> <tr> <td> \[ <a> IEEE Std 1003.1:2013 </a> \] </td> <td> 2.4.1, Signal Generation and Delivery </td> </tr> <tr> <td> \[ <a> ISO/IEC 9899:2011 </a> \] </td> <td> Subclause 7.14.1.1, "The <code>signal</code> Function" </td> </tr> </tbody> </table>


## Implementation notes

None

## References

* CERT-C: [SIG35-C: Do not return from a computational exception signal handler](https://wiki.sei.cmu.edu/confluence/display/c)
