exponenta event banner

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).

Пример - Выделение массива символов с помощью sizeof
#include <stdlib.h>

void test_case_1(void) {
    char* str;

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

}

В этом примере память выделяется для указателя символа str использование malloc из пяти стрелочных указателей. Однако 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 оператор для имени параметра массива, ожидающий размер массива. Однако имя параметра массива само по себе является указателем. 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 для выделения буфера, размер буфера меньше требуемого. Недостаток буфера может привести к возникновению таких недостатков, как переполнение буфера.

  • Если используется возвращаемое значение 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;
    }
}

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

Группа: Rec. 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 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

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