Use of setjmp/longjmp

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 операторы.

Примеры

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

#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;
}

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

Группа: Хорошая практика
Язык: C | C++
Значение по умолчанию: 'off'
Синтаксис командной строки: SETJMP_LONGJMP_USE
Удар: низко
ID CWE: 691

Введенный в R2015b