exponenta event banner

CERT C: Rec. MEM04-C

Остерегайтесь нулевых назначений

Описание

Определение правила

Остерегайтесь нулевых назначений. [1 ]

Внедрение Polyspace

Эта проверка проверяет наличие следующих проблем:

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

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

  • Запятнанный размер массива переменной длины.

Примеры

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

Проблема

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

Риск

Согласно стандарту C (C11, Subclause 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

Одной из возможных корректировок является проверка переменной размера перед созданием массива переменной длины. В этом примере перед созданием VLA проверяется, превышает ли размер 0 и меньше 40.

#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 Университет Карнеги-Меллон, веб-сайт SEI CERT-C + + © 2017 Университет Карнеги-Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги-Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОНА И/ИЛИ ЕГО ПРОГРАММНОГО ИНЖЕНЕРНОГО ИНСТИТУТА, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ КАК ЕСТЬ. УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБЫХ ВОПРОСОВ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИИ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ ТОВАРНОЙ ПРИГОДНОСТИ, ИСКЛЮЧИТЕЛЬНОСТИ ИЛИ РЕЗУЛЬТАТОВ, ПОЛУЧЕННЫХ ОТ ИСПОЛЬЗОВАНИЯ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Данное программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллона или его Институтом разработки программного обеспечения.