CERT C: Rec. MSC22-C

Безопасно используйте средства setjmp (), longjmp ()

Описание

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

Используйте средство setjmp (), longjmp () безопасно.[1]

Реализация Polyspace

Эта проверка проверяет на Использование setjmp/longjmp.

Примеры

расширить все

Проблема

Использование setjmp/longjmp происходит, когда вы используете комбинацию setjmp и longjmp или sigsetjmp и siglongjmp чтобы отклониться от нормального потока управления и выполнить нелокальные переходы в коде.

Риск

Использование setjmp и longjmp, или sigsetjmp и siglongjmp имеет следующие риски:

  • Нелокальные переходы уязвимы для атак, которые используют общие ошибки, такие как переполнение буфера. Злоумышленники могут перенаправить поток управления и потенциально выполнить произвольный код.

  • Ресурсы, такие как динамически выделенная память и открытые файлы, могут не быть закрыты, что приводит к утечке ресурсов.

  • Если вы используете setjmp и longjmp в комбинации с обработчиком сигнала может возникнуть неожиданный поток управления. POSIX® не указывает, setjmp сохраняет маску сигнала.

  • Использование setjmp и longjmp или sigsetjmp и siglongjmp затрудняет понимание и обслуживание вашей программы.

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

Выполните нелокальные переходы в коде, используя setjmp/longjmp или sigsetjmp/siglongjmp только в контекстах, где такие переходы могут выполняться безопасно. Кроме того, по возможности используйте потоки POSIX.

В C++, чтобы симулировать броски и улавливание исключений, используйте стандартные идиомы, такие как throw выражения и catch операторы.

Пример - Использование setjmp и longjmp
#include <setjmp.h>
#include <signal.h>

extern int update(int);
extern void print_int(int);

static jmp_buf env;
void sighandler(int signum) {
    longjmp(env, signum);
}
void func_main(int i) {
    signal(SIGINT, sighandler);
    if (setjmp(env)==0) {
        while(1) {
            /* Main loop of program, iterates until SIGINT signal catch */
            i = update(i);
        }
    } else {
        /* Managing longjmp return */
        i = -update(i);
    }

    print_int(i);
    return;
}

В этом примере начальное значение возврата setjmp равен 0. The update функция вызывается в бесконечном while цикл, пока пользователь не прерывает его через сигнал.

В функции обработки сигналов longjmp оператор вызывает обратный переход к main и возврат значение setjmp теперь равен 1. Поэтому else ветвь выполняется.

Коррекция - используйте альтернативу setjmp и longjmp

Чтобы более безопасно эмулировать то же поведение, используйте volatile глобальная переменная вместо комбинации setjmp и longjmp.

#include <setjmp.h>
#include <signal.h>

extern int update(int);
extern void print_int(int);

volatile sig_atomic_t eflag = 0;

void sighandler(int signum) {
     eflag = signum;                   /* Fix: using global variable */
}

void func_main(int i) {
      /* Fix: Better design to avoid use of setjmp/longjmp */
    signal(SIGINT, sighandler);
    while(!eflag) {                   /* Fix: using global variable */
        /* Main loop of program, iterates until eflag is changed */
        i = update(i);
    }

    print_int(i);
    return;
}

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

Группа: Rec. 48. Разное (MSC)
Введенный в R2019a

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

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

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