CERT C: Rule MEM35-C

Выделите достаточную память для объекта

Описание

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

Выделите достаточную память для object.[1]

Реализация Polyspace

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

  • Доступ к указателю за пределы.

  • Выделение памяти с испорченным размером.

  • Неправильно введите используемый в sizeof во время выделения памяти

Примеры

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

Проблема

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

Когда указатель присвоен адрес, блок памяти сопоставлен с указателем. Вы не можете получить доступ к памяти, кроме того блокируют использование указателя.

Риск

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

Фиксация

Фиксация зависит от первопричины дефекта. Например, вы разыменовали указатель в цикле, и одна из этих ситуаций произошла:

  • Верхняя граница цикла является слишком большой.

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

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

Часто детали результата показывают последовательность событий, которые привели к дефекту. Можно реализовать закрепление на любом событии в последовательности. Если детали результата не показывают историю события, можно проследить использование, щелкните правой кнопкой по опциям по исходному коду и смотрите предыдущие связанные события. См. также Интерпретируют Результаты Bug Finder в Пользовательском интерфейсе Рабочего стола Polyspace.

Смотрите примеры мер ниже.

Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.

Пример - доступ к Указателю за пределы ошибка
int* Initialize(void)
{
 int arr[10];
 int *ptr=arr;

 for (int i=0; i<=9;i++)
   {
    ptr++;
    *ptr=i;
    /* Defect: ptr out of bounds for i=9 */
   }

 return(arr);
}

ptr присвоен адрес arr это указывает на блок памяти размера 10*sizeof(int). В for- цикл, ptr постепенно увеличивается 10 раз. В последней итерации цикла, ptr точки вне блока памяти, присвоенного ему. Поэтому это не может быть разыменовано.

Коррекция — указатель проверки остается внутри границ

Одна возможная коррекция должна инвертировать порядок шага и разыменовать ptr.

int* Initialize(void)
{
 int arr[10];
 int *ptr=arr;

 for (int i=0; i<=9;i++)
     {
      /* Fix: Dereference pointer before increment */
      *ptr=i;
      ptr++;
     }

 return(arr);
}

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

Проблема

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

Риск

Неконтролируемое выделение памяти может заставить вашу программу запрашивать слишком много системной памяти. Это последствие может привести к катастрофическому отказу из-за условия из памяти, или присваивающий слишком много ресурсов.

Фиксация

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

Пример — выделяет память Используя вход от пользователя
#include<stdio.h>
#include <stdlib.h>

int* bug_taintedmemoryallocsize(void) {
    size_t size;
    scanf("%zu", &size);
    int* p = (int*)malloc(size);
    return p;
}

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

Коррекция — Размер Проверки Памяти, которая будет Выделена

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

#include<stdio.h>
#include <stdlib.h>

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

int* corrected_taintedmemoryallocsize(void) {
    size_t size;
    scanf("%zu", &size);
    int* p = NULL;
    if (size>0 && size<SIZE128) {          /* Fix: Check entry range before use */
        p = (int*)malloc((unsigned int)size);
    }
    return p;
}
Проблема

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

Риск

Независимо от какой type обозначает, выражение sizeof (type*) всегда возвращает размер указателя на вашей платформе в байтах. Если вы непреднамеренно используете sizeof (type*) вместо sizeof (type) в вашем malloc оператор, выделенный блок памяти может быть меньшим, чем, в чем вы нуждаетесь. Эта ошибка может вызвать дефекты, такие как переполнение буфера.

Считайте структуру structType, который содержит 10 int переменные. Если вы инициализируете structType* указатель при помощи malloc(sizeof(structType*)) на 32-битной платформе указатель присвоен блок памяти четырех байтов. Этот блок памяти недостаточен для structType структура, которая требует, по крайней мере, 10 * sizeof(int) байты. Поскольку необходимый размер очень больше фактического выделенного размера, с помощью structType* вместо structType в качестве аргумента sizeof результаты в переполнении.

Фиксация

При выделении блоков памяти для указателей используйте sizeof (type) вместо sizeof (type*).

Пример — выделяет массив структур при помощи sizeof Оператор в malloc Оператор
#include <stdlib.h>
typedef struct user{
	long uid;
	long euid;
	int number;
	int address;
	int value;
} USER;

void Noncompliant(void) {
	USER* user_list;
	user_list = (USER*)malloc(sizeof(USER*) * 5);
	/*...*/
	free(user_list);

}

В этом примере память динамически выделяется для массива user_list который содержит пять экземпляров структуры USER. Этот массив требует по крайней мере 50 байтов памяти, потому что каждый элемент массива требует по крайней мере 10 байтов памяти. В malloc оператор, USER* используется в качестве аргумента для sizeof оператор вместо USER, возможно, непреднамеренно. В результате размер выделенного блока памяти может составить 20 байтов, который очень меньше необходимой памяти. Эта ошибка может привести к переполнению буфера.

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

Одна возможная коррекция должна использовать тип объекта, на который указывает указатель как вход к sizeof. Например, используйте USER вместо USER* при выделении памяти для массива USER.

#include <stdlib.h>
typedef struct user{
	long uid;
	long euid;
	int number;
	int address;
	int value;
} USER;

void Compliant(void) {
	USER* user_list;
	user_list = (USER*)malloc(sizeof(USER) * 5);
	/*...*/
	free(user_list);

}

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

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

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