CERT C: Rec. MEM05-C

Избегайте больших выделений стека

Описание

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

Избегайте большого стека allocations.[1]

Реализация Polyspace

Это средство проверки проверяет на эти проблемы:

  • Прямой или косвенный вызов функции к себе.

  • Массив переменной длины с неположительным размером.

  • Испорченный размер массива переменной длины.

Примеры

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

Проблема

Проблема происходит, когда ваш код содержит функции, которые вызывают себя прямо или косвенно.

Риск

Переменные, локальные для функции, хранятся в стеке вызовов. Если вызовы функции самостоятельно прямо или косвенно несколько раз, доступное стековое пространство может быть превышено, вызвав серьезный отказ. Если рекурсией плотно не управляют, она затрудняет, чтобы определить максимальное требуемое стековое пространство.

Пример - прямая и косвенная рекурсия
void foo1( void ) {     /* Non-compliant - Indirect recursion foo1->foo2->foo1... */
    foo2();
    foo1();               /* Non-compliant - Direct recursion */
}

void foo2( void ) {
    foo1();
}

В этом примере правило нарушено из-за:

  • Прямая рекурсия foo1foo1.

  • Косвенная рекурсия foo1foo2foo1.

Проблема

Массив переменной длины с неположительным размером происходит, когда размер массива переменной длины является нулем или отрицательный.

Риск

Если размер массива переменной длины является нулем, или отрицательное, неожиданное поведение может произойти, такие как переполнение стека.

Фиксация

Когда вы объявляете массив переменной длины как локальную переменную в функции:

  • Если вы используете параметр функции в качестве размера массивов, проверяйте, что параметр положителен.

  • Если вы используете результат расчета на параметре функции как размер массивов, проверяйте, что результат положителен.

Можно поместить тест для положительного значения или перед вызовом функции или перед объявлением массива в теле функции.

Пример - неположительный размер массивов
int input(void);

void add_scalar(int n, int m) {
    int r=0;
    int arr[m][n];
    for (int i=0; i<m; i++) {
        for (int j=0; j<n; j++) {
            arr[i][j] = input();
            r += arr[i][j];
        }
    }
}

void main() {
    add_scalar(2,2);
    add_scalar(-1,2);
    add_scalar(2,0);
}

В этом примере, вторых и третьих вызовах add_scalar приведите к отрицательному и нулевому размеру arr.

Коррекция — делает размер массивов положительным

Одна возможная коррекция является фиксацией, или удалите вызовы, которые приводят к неположительному размеру массивов.

Проблема

Испорченный размер массива переменной длины обнаруживает массивы переменной длины (VLA), размер которых из небезопасного источника.

Риск

Если атакующий изменил размер вашего VLA к неожиданному значению, это может заставить вашу программу отказывать или неожиданно вести себя.

Если размер неположителен, поведение VLA не определено. Ваша программа не выполняет как ожидалось.

Если размер неограничен, VLA может вызвать исчерпание памяти или переполнение стека.

Фиксация

Подтвердите свой размер VLA, чтобы убедиться, что это положительно и меньше, чем максимальное значение.

Пример - входной параметр, используемый в качестве размера VLA
enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};

int taintedvlasize(int size) {

    int tabvla[size];
    int res = 0;
    for (int i=0 ; i<SIZE10 ; ++i) {
        tabvla[i] = i*i;
        res += tabvla[i];
    }
    return res;
}

В этом примере размер переменной длины массивов основан на входном параметре. Поскольку это значение входного параметра не проверяется, размер может быть отрицательным или слишком большим.

Коррекция — проверяет размер VLA

Одна возможная коррекция должна проверять переменную размера прежде, чем создать массив переменной длины. Этот пример проверяет, больше ли размер, чем 10 и меньше чем 100, прежде, чем создать VLA

enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};

int taintedvlasize(int size) {
    int res = 0;
    if (size>SIZE10 && size<SIZE100) {
        int tabvla[size]; 
        for (int i=0 ; i<SIZE10 ; ++i) {
            tabvla[i] = i*i;
            res += tabvla[i];
        }
    }
    return res;
}

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

Группа: Rec. 08. Управление памятью (MEM)
Введенный в 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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