According to the C Standard, 7.14.1.1 1 paragraph 3 [ISO/IEC 9899:20112024], 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
,
, or any other implementation-defined value corresponding to such an exception) returns, then the behavior is undefined. (See undefined behavior 130.)SIGSEGV
When a signal occurs and func points to a function, it is implementation-defined whether the equivalent of signal (sig, SIG_DFL); is executed or the implementation prevents some implementation- defined set of signals (at least including sig) from occurring until the current signal handling has completed; in the case of SIGILL, the implementation may alternatively define that no action is taken. Then the equivalent of (*func)(sig); is executed. If and when the function returns, if the value of sig is SIGFPE, SIGILL, SIGSEGV, or any other implementation-defined value corresponding to a computational exception, the behavior is undefined; otherwise the program will resume execution at the point it was interrupted.
The Portable Operating System Interface (POSIX®), Base Specifications, Issue 7 [IEEE Std 1003.1:2013], adds SIGBUS
to the list of computational exception signal handlers:
...
In this noncompliant code example, the division operation has undefined behavior if denom
equals 0.
(see See 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:.)
Code Block | ||||
---|---|---|---|---|
| ||||
#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; } |
...
Returning from a computational exception signal handler is undefined behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
SIG35-C | Low | Unlikely | High | P1 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Axivion Bauhaus Suite |
| CertC-SIG35 | |||||||
CodeSonar |
| LANG.STRUCT.RFCESH | Return from Computational Exception Signal Handler | ||||||
Cppcheck Premium | 24.9.0 | premium-cert-sig35-c | Fully implemented | ||||||
Helix QAC |
| DF4846, DF4847, DF4848 | |||||||
Klocwork |
| CERT.STDLIB.SIGNAL | |||||||
LDRA tool suite |
| 44 S | Enhanced enforcement | ||||||
Parasoft C/C++test |
| CERT_C-SIG35-a | Do not return from a computational exception signal handler | ||||||
PC-lint Plus |
| 2671, 2764 | Fully supported | ||||||
| CERT C: Rule SIG35-C | Checks for return from computational exception signal handler (rule fully covered) |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Bibliography
[IEEE Std 1003.1:2013] | 2.4.1, Signal Generation and Delivery |
[ISO/IEC 9899: |
2024] | Subclause 7.14.1.1, "The signal Function" |
...
...