CERT C++: ERR52-CPP

Не используйте 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;
}

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

Группа: 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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