exponenta event banner

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. 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 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

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