exponenta event banner

Функция, вызываемая из обработчика сигнала, не является асинхронно-безопасной (strict)

Вызов прерванной функции вызывает неопределенное поведение программы

Описание

Этот дефект возникает, когда обработчик сигнала вызывает функцию, которая не является асинхронно-безопасной в соответствии со стандартом C. Асинхронно-безопасная функция может быть прервана в любой момент ее выполнения, затем вызвана снова, не вызывая противоречивого состояния. Он также может правильно обрабатывать глобальные данные, которые могут находиться в несогласованном состоянии.

При выборе функции checker, вызываемой из обработчика сигналов, которая не является асинхронно-безопасной, программа checker обнаруживает вызовы функций, которые не являются асинхронно-безопасными в соответствии со стандартом POSIX. Функция, вызываемая из обработчика сигнала, не является асинхронно-безопасной (строгой), не вызывает дефекта в этих случаях. Функция, вызываемая из обработчика сигнала, не является асинхронно-безопасной (строгой), вызывает дефект для функций, которые являются асинхронно-безопасными в соответствии со стандартом POSIX, но не в соответствии со стандартом C.

Если обработчик сигнала вызывает другую функцию, которая вызывает асинхронно-небезопасную функцию, дефект появляется в вызове функции в обработчике сигнала. Трассировка дефектов показывает полный путь от обработчика сигнала к функции асинхронной безопасности.

Риск

При вызове обработчика сигнала выполнение программы прерывается. После завершения работы обработчика выполнение программы возобновляется в точке прерывания. Если функция выполняется во время прерывания, вызов ее из обработчика сигнала является неопределенным поведением, если только она не является асинхронно-безопасной.

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

Стандарт C определяет следующие функции как асинхронно-безопасные. Можно вызвать следующие функции из обработчика сигнала:

  • abort()

  • _Exit()

  • quick_exit()

  • signal()

Примеры

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

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
#include <syslog.h>
#include <unistd.h>

void SIG_ERR_handler(int signum)
{
    int s0 = signum;
    /* SIGTERM specific handling */
}

void sig_handler(int signum)
{
    int s0 = signum;
	/* Call raise() */ 
    if (raise(SIGTERM) != 0) { 
        /* Handle error */
    }
}

int finc(void)
{
    if (signal(SIGTERM, SIG_ERR_handler) == SIG_ERR)
    {
        /* Handle error */
    }
    if (signal(SIGINT, sig_handler) == SIG_ERR)
    {
        /* Handle error */
    }
    /* Program code */
    if (raise(SIGINT) != 0)
    {
        /* Handle error */
    }
    /* More code */
    return 0;
}
        
      

В этом примере: sig_handler требования raise() при захвате сигнала. Если обработчик перехватывает другой сигнал во время raise() выполняется, поведение программы не определено.

Исправление - Удаление вызова raise() в обработчике сигналов

Согласно стандарту C, единственными функциями, которые можно безопасно вызвать из обработчика сигнала, являются abort(), _Exit(), quick_exit(), и signal().

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
#include <syslog.h>
#include <unistd.h>

void SIG_ERR_handler(int signum)
{
    int s0 = signum;
    /* SIGTERM specific handling */
}
void sig_handler(int signum)
{
    int s0 = signum;
	
  
}

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

Информация о результатах

Группа: Программирование
Язык: C | C++
По умолчанию: Откл.
Синтаксис командной строки: SIG_HANDLER_ASYNC_UNSAFE_STRICT
Воздействие: среднее
CWE ID: 364, 387, 413, 479, 663, 828
Представлен в R2017b