CERT C++: ERR52-CPP

Не используйте setjmp () или longjmp ()

Описание

Управляйте определением

Не используйте setjmp () или longjmp (). [1]

Примеры

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

Описание

Использование 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;
}

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

Группа: 08. Исключения и обработка ошибок (ERR)

Введенный в R2019a


[1]  Это программное обеспечение было создано MathWorks, включающим фрагменты: “Веб-сайт SEI CERT-C”, © 2017 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

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

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