Main Content

CERT C: Rule ERR32-C

Do not rely on indeterminate values of errno

Description

Rule Definition

Do not rely on indeterminate values of errno.1

Polyspace Implementation

The rule checker checks for Misuse of errno in a signal handler.

Examples

expand all

Issue

Misuse of errno in a signal handler occurs when you call one of these functions in a signal handler:

  • signal: You call the signal function in a signal handler and then read the value of errno.

    For instance, the signal handler function handler calls signal and then calls perror, which reads errno.

    typedef void (*pfv)(int);
    
    void handler(int signum) {
      pfv old_handler = signal(signum, SIG_DFL);
      if (old_handler == SIG_ERR) {
        perror("SIGINT handler"); 
      }
    }

  • errno-setting POSIX® function: You call an errno-setting POSIX function in a signal handler but do not restore errno when returning from the signal handler.

    For instance, the signal handler function handler calls waitpid, which changes errno, but does not restore errno before returning.

    #include <stddef.h>
    #include <errno.h>
    #include <sys/wait.h>
    
    void handler(int signum) {
      int rc = waitpid(-1, NULL, WNOHANG);
      if (ECHILD != errno) {
      }
    }

Risk

In each case that the checker flags, you risk relying on an indeterminate value of errno.

  • signal: If the call to signal in a signal handler fails, the value of errno is indeterminate (see C11 Standard, Sec. 7.14.1.1). If you rely on a specific value of errno, you can see unexpected results.

  • errno-setting POSIX function: An errno-setting function sets errno on failure. If you read errno after a signal handler is called and the signal handler itself calls an errno-setting function, you can see unexpected results.

Fix

Avoid situations where you risk relying on an indeterminate value of errno.

  • signal: After calling the signal function in a signal handler, do not read errno or use a function that reads errno.

  • errno-setting POSIX function: Before calling an errno-setting function in a signal handler, save errno to a temporary variable. Restore errno from this variable before returning from the signal handler.

Example - Reading errno After signal Call in Signal Handler
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

#define fatal_error() abort()

void handler(int signum) {
    if (signal(signum, SIG_DFL) == SIG_ERR) {
        perror("SIGINT handler");
    }
} //Noncompliant

int func(void) {
    if (signal(SIGINT, handler) == SIG_ERR) {
        /* Handle error */
        fatal_error();
    }
    /* Program code */
    if (raise(SIGINT) != 0) {
        /* Handle error */
        fatal_error();
    }
    return 0;
}

In this example, the function handler is called to handle the SIGINT signal. In the body of handler, the signal function is called. Following this call, the value of errno is indeterminate. The checker raises a defect when the perror function is called because perror relies on the value of errno.

Correction — Avoid Reading errno After signal Call

One possible correction is to not read errno after calling the signal function in a signal handler. The corrected code here calls the abort function via the fatal_error macro instead of the perror function.

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

#define fatal_error() abort()

void handler(int signum) {
    if (signal(signum, SIG_DFL) == SIG_ERR) {
        fatal_error();
    }
} 

int func(void) {
    if (signal(SIGINT, handler) == SIG_ERR) {
        /* Handle error */
        fatal_error();
    }
    /* Program code */
    if (raise(SIGINT) != 0) {
        /* Handle error */
        fatal_error();
    }
    return 0;
}

Check Information

Group: Rule 12. Error Handling (ERR)

Version History

Introduced in R2019a


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.