CERT C: Rec. MEM04-C

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

Описание

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

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

Реализация Polyspace

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

  • Нулевое выделение памяти длины

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

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

Примеры

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

Проблема

Нулевое выделение памяти длины происходит, когда выделение памяти функционирует, такие как malloc или calloc берет аргумент размера (или число элементов), который может содержать нуль значения.

Риск

Согласно Стандарту C (C11, Подпункт 7.22.3), если память нулевого размера требуют от функции выделения памяти, задано реализацией поведение. В некоторых реализациях функциональная сила возвращает NULL, и ваша существующая защита против NULL может быть достаточной, чтобы защитить от нулевого выделения длины. В других случаях функциональная сила возвращает область памяти, к которой нельзя получить доступ. Попытки разыменовать эту область приводят к неопределенному поведению.

Фиксация

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

Пример – возможно обнуляет аргумент размера к malloc
#include <stdlib.h>

void  func(unsigned int size) {
    int *list = (int *)malloc(size);
    if (list == NULL) {
      /* Handle allocation error */
    }
    else {
    /* Continue processing list */
    }
}

В этом примере, переменной size может содержать нуль значения, ведущий к нулевому выделению памяти длины.

Коррекция – проверяет на нуль перед использованием переменной как размер

Подтвердите внешние входные параметры для нулевых значений перед использованием в качестве аргумента размера к malloc функция.

#include <stdlib.h>

void  func(unsigned int size) {
    if(size == 0) {
        /* Handle zero size error */
    }
    else {
        int *list = (int *)malloc(size);
        if (list == NULL) {
          /* Handle allocation error */
        }
        else {
          /* Continue processing list */
        }
    }
}
Проблема

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

Риск

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

Фиксация

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

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

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

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

Пример - неположительный размер массивов
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
#include<stdio.h>
#inclule<stdlib.h>
#define LIM 40

long squaredSum(int size) {

	int tabvla[size];
	long res = 0;
	for (int i=0 ; i<LIM-1 ; ++i) {
		tabvla[i] = i*i;
		res += tabvla[i];
	}
	return res;
}
int main(){
	int size;
	scanf("%d",&size);
	//...
	long result = squaredSum(size);
	//...
	return 0;
}

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

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

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

#include <stdio.h>
#include <stdlib.h>
#define LIM 40

long squaredSum(int size) {
	long res = 0;
	if (size>0 && size<LIM){
		int tabvla[size];
		for (int i=0 ; i<size || i<LIM-1 ; ++i) {
			tabvla[i] = i*i;
			res += tabvla[i];
		}
	}else{
		res = -1;
	}
	return res;
}
int main(){
	int size;
	scanf("%d",&size);
	//...
	long result = squaredSum(size);
	//...
	return 0;
}

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

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

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