CERT C: Rec. MEM04-C

Остерегайтесь выделений нулевой длины

Описание

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

Остерегайтесь выделений нулевой длины. [1]

Примеры

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

Описание

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

Риск

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

Фиксация

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

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

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

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

Пример - неположительный размер массивов

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.

Исправление — делает размер массивов положительным

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

Описание

Испорченное преобразование изменения знака ищет значения из небезопасных источников, которые преобразованы, неявно или явным образом, от со знаком до значений без знака.

Например, функции, которые используют size_t в качестве аргументов неявно, преобразовывают аргумент в беззнаковое целое. Некоторые функции, которые неявно преобразовывают size_t:

bcmp
memcpy
memmove
strncmp
strncpy
calloc
malloc
memalign

Риск

Если вы преобразовываете маленькое отрицательное число в без знака, результатом является большое положительное число. Большое положительное число может создать уязвимости системы обеспечения безопасности. Например, если вы используете значение без знака в:

  • Стандартные программы емкости памяти — причины, выделяющие проблемы памяти.

  • Стандартные программы обработки строк — вызывают переполнение буфера.

  • Контуры цикла — вызывают бесконечные циклы.

Фиксация

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

Пример - значение памяти аппарата с аргументом размера

#include <stdlib.h>
#include <string.h>

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

void bug_taintedsignchange(int size) {
    char str[SIZE128] = "";
    if (size<SIZE128) {
        memset(str, 'c', size); 
    }
}

В этом примере буфер char создается и заполнил использование memset. Аргумент размера к memset является входным параметром к функции.

Вызов memset неявно преобразовывает size в беззнаковое целое. Если size является большим отрицательным числом, абсолютное значение могло бы быть слишком большим, чтобы представлять как целое число, вызвав переполнение буфера.

Исправление — контрольное число size

Одно возможное исправление должно проверять, ли size в допустимой области значений. Это исправление проверяет, больше ли size, чем нуль и меньше, чем buffer size прежде, чем вызвать memset.

#include <stdlib.h>
#include <string.h>

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

void corrected_taintedsignchange(int size) {
    char str[SIZE128] = "";
    if (size>0 && size<SIZE128) {
        memset(str, 'c', size);  
    }
}

Описание

Испорченный размер массива переменной длины обнаруживает массивы переменной длины (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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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