exponenta event banner

CERT C: ERR32-C правил

Не полагайтесь на неопределенные значения errno

Описание

Определение правила

Не полагайтесь на неопределенные значения errno. [1 ]

Внедрение Polyspace

Эта проверка проверяет неправильное использование errno в обработчике сигналов.

Примеры

развернуть все

Проблема

Неправильное использование errno в обработчике сигнала происходит при вызове одной из следующих функций в обработчике сигнала:

  • signal: Вы называете signal функция в обработчике сигнала, а затем считывание значения errno.

    Например, функция обработчика сигнала handler требования signal а затем звонит perror, который гласит: 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-настройка функции POSIX ®: вы вызываете errno-настройка функции POSIX в обработчике сигналов, но не восстановление errno при возврате от обработчика сигнала.

    Например, функция обработчика сигнала handler требования waitpid, который изменяется errno, но не восстанавливает errno перед возвращением.

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

Риск

В каждом случае, когда средство проверки помечает, вы рискуете полагаться на неопределенное значение errno.

  • signal: Если вызов signal в обработчике сигнала, значение errno является неопределенным (см. C11 Стандарт, раздел 7.14.1.1). Если вы полагаетесь на определенное значение errno, вы можете увидеть неожиданные результаты.

  • errno-настройка функции POSIX: errno-настройка наборов функций errno при отказе. Если вы читаете errno после вызова обработчика сигнала, и сам обработчик сигнала вызывает errno-настройка функции, можно увидеть неожиданные результаты.

Зафиксировать

Избегайте ситуаций, когда вы рискуете полагаться на неопределенное значение errno.

  • signal: После вызова signal функция в обработчике сигнала, не считывайте errno или используйте функцию, которая считывает errno.

  • errno-настройка функции POSIX: перед вызовом errno-настройка функции в обработчике сигналов, сохранение errno к временной переменной. Восстановить errno от этой переменной перед возвратом от обработчика сигнала.

Пример - чтение errno После signal Обработчик сигнала вызова
#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");
    }
}

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;
}

В этом примере функция handler вызывается для обработки SIGINT сигнал. В теле handler, signal вызывается функция. После этого вызова значение errno является неопределенным. Шашка поднимает дефект, когда perror функция вызывается, поскольку perror полагается на значение errno.

Исправление - избегайте чтения errno После signal Звонить

Одно из возможных исправлений - не читать errno после вызова signal функция в обработчике сигнала. Исправленный код вызывает abort через fatal_error макро вместо perror функция.

#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;
}

Проверить информацию

Группа: Правило 12. Обработка ошибок (ERR)
Представлен в R2019a

[1] Данное программное обеспечение было создано компанией MathWorks и включает в себя следующие компоненты: «Веб-сайт SEI CERT-C», © 2017 Университет Карнеги-Меллон, веб-сайт SEI CERT-C + + © 2017 Университет Карнеги-Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги-Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОНА И/ИЛИ ЕГО ПРОГРАММНОГО ИНЖЕНЕРНОГО ИНСТИТУТА, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ КАК ЕСТЬ. УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБЫХ ВОПРОСОВ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИИ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ ТОВАРНОЙ ПРИГОДНОСТИ, ИСКЛЮЧИТЕЛЬНОСТИ ИЛИ РЕЗУЛЬТАТОВ, ПОЛУЧЕННЫХ ОТ ИСПОЛЬЗОВАНИЯ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Данное программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллона или его Институтом разработки программного обеспечения.