CERT C: Rec. ARR01-C

Не применяйте оператор sizeof к указателю при взятии размера массива

Описание

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

Не применяйте оператор sizeof к указателю при взятии размера массива.[1]

Реализация Polyspace

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

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

  • Возможное неправильное использование sizeof.

Примеры

расширить все

Проблема

Неправильный тип, используемый в sizeof, возникает, когда оба из следующих условий удерживаются:

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

    Например, вы инициализируете указатель, используя malloc (sizeof (type)) или скопируйте данные между двумя адресами с помощью memcpy (destination_ptr, source_ptr, sizeof (type)).

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

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

Риск

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

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

Зафиксировать

Как инициализировать type* указатель, замените sizeof (type*) в выражении инициализации указателя с sizeof (type).

Пример - Выделение массива Char с sizeof
#include <stdlib.h>

void test_case_1(void) {
    char* str;

    str = (char*)malloc(sizeof(char*) * 5);
    free(str);

}

В этом примере память выделяется для символьного указателя str использование malloc из пяти указателей char. Однако str - указатель на символ, а не указатель на символьный указатель. Поэтому sizeof аргумент, char*, неправильный.

Коррекция - соответствие типа указателя на sizeof Аргумент

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

#include <stdlib.h>

void test_case_1(void) {
    char* str;

    str = (char*)malloc(sizeof(char) * 5);
    free(str);

}
Проблема

Возможное неправильное использование sizeof происходит, когда Polyspace® Bug Finder™ обнаруживает возможно непреднамеренные результаты от использования sizeof оператор. Для образца:

  • Вы используете sizeof оператор для имени параметра массива, ожидающий размера массива. Однако имя параметра массива само по себе является указателем. The sizeof оператор возвращает размер этого указателя.

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

  • Аргумент размера некоторых функций, таких как strncmp или wcsncpy неправильный, поскольку вы использовали sizeof оператор ранее с возможно неправильными ожиданиями. Для образца:

    • В вызове функции strncmp(string1, string2, num), num получено из-за неправильного использования sizeof оператор на указателе.

    • В вызове функции wcsncpy(destination, source, num), num - это не количество широких символов, а размер в байтах, полученных при помощи sizeof оператор. Например, вы используете wcsncpy(destination, source, sizeof(destination) - 1) вместо wcsncpy(destination, source, (sizeof(desintation)/sizeof(wchar_t)) - 1).

Риск

Неправильное использование sizeof оператор может вызвать следующие проблемы:

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

  • Если вы используете возврат значение sizeof оператор для выделения буфера, buffer size меньше, чем требуется. Недостаточный буфер может привести к результирующим слабостям, таким как переполнение буфера.

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

Зафиксировать

Возможные исправления:

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

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

  • Используйте sizeof оператор, чтобы тщательно определить число аргументов функций, таких как strncmp или wcsncpy. Например, для широких строковых функций, таких как wcsncpy, используйте количество широких символов в качестве аргумента вместо количества байтов.

Пример - sizeof Неправильное использование для определения размера массива
#define MAX_SIZE 1024

void func(int a[MAX_SIZE]) {
    int i;

    for (i = 0; i < sizeof(a)/sizeof(int); i++)    {
        a[i] = i + 1;
    }
}

В этом примере sizeof(a) возвращает размер указателя a а не размер массива.

Коррекция - определите размер массива другим способом

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

#define MAX_SIZE 1024

void func(int a[MAX_SIZE]) {
    int i;

    for (i = 0; i < MAX_SIZE; i++)    {
        a[i] = i + 1;
    }
}

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

Группа: Рек. 06. Массивы (ARR)
Введенный в R2019a

[1] Это программное обеспечение было создано MathWorks, включающее фрагменты: «Сайт SEI CERT-C», © 2017 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

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

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