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

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