CERT C: Rec. ARR01-C

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

Описание

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

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

Примеры

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

Описание

Неправильно введите используемый в 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, чтобы выделить буфер, 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;
    }
}

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

Группа: Rec. 06. Массивы (ARR)

Введенный в 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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