CERT C++: EXP39-C

Не получайте доступ к переменной через указатель несовместимого типа

Описание

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

Не получайте доступ к переменной через указатель несовместимого типа.[1]

Реализация Polyspace

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

  • Преобразование указателя в несвязанный тип указателя

  • Чтение памяти, перераспределенной от объекта другого типа, не повторно инициализируя сначала

.

Примеры

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

Проблема

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

Риск

Результат преобразования между указателями несвязанных типов не задан в стандарте C. Такое преобразование может привести к неожиданному поведению.

Исправление

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

Проблема

Эта проблема происходит, когда вы делаете следующее в последовательности:

  1. Перераспределите память объекту с типом, который отличается от исходного выделения.

    Например, в этом фрагменте кода, память, первоначально выделенная указателю с типом struct A* перераспределен к указателю с типом struct B*:

    struct A;
    struct B;
    
    struct A *Aptr = (struct A*) malloc(sizeof(struct A));
    struct B *Bptr = (struct B*) realloc(Aptr, sizeof(struct B));

  2. Читайте из этой перераспределенной памяти, не повторно инициализируя память сначала.

    Доступ для чтения на указателе на перераспределенную память может произойти через указатель, разыменовывают или индексация массива. Передача указателя на функцию, которая берет указатель на const- квалифицированный объект как соответствующий параметр также рассчитывает как доступ для чтения.

Риск

Чтение из перераспределенной памяти, которая не была повторно инициализирована, является неопределенным поведением.

Исправление

Повторно инициализируйте память после перераспределения и перед первым доступом для чтения.

Средство проверки рассматривает любой доступ для записи на указателе на перераспределенную память как удовлетворение требованию реинициализации (даже если объектная сила только быть частично повторно инициализированным). Доступ для записи на указателе на перераспределенную память может произойти через указатель, разыменовывают или индексация массива. Передача указателя на функцию, которая берет указатель на non-const- квалифицированный объект как соответствующий параметр также рассчитывает как доступ для записи.

Пример – несовместимый: чтение из перераспределенной памяти, не повторно инициализируя сначала
#include<cstdlib>

struct group {
    char *groupFirst;
    int groupSize;
};

struct groupWithID {
    int groupID;
    char *groupFirst;
    int groupSize;
};

char* readName();
int readSize();

void createGroup(int nextAvailableID) {
    struct group *aGroup;
    struct groupWithID *aGroupWithID;
    
    aGroup = (struct group*) malloc(sizeof(struct group));
    aGroup->groupFirst = readName();
    aGroup->groupSize  = readSize();
    
    if(!aGroup) {
        /*Handle error*/
    }
    
    /* Reassign to group with ID */
    aGroupWithID = (struct groupWithID*) realloc(aGroup, sizeof(struct groupWithID));
    if(!aGroupWithID) {
        free(aGroup);
        /*Handle error*/
    }
    
    if(aGroupWithID -> groupSize > 0) { /* Noncompliant */
        /* ... */
    }
    
    /* ...*/
    free(aGroupWithID);
}

В этом примере, память, выделенная group* указатель с помощью malloc функция перераспределена к groupWithID* указатель с помощью realloc функция. Существует доступ для чтения на перераспределенной памяти, прежде чем память будет повторно инициализирована.

Коррекция – повторно инициализирует память после перераспределения и прежде сначала чтение

Повторно инициализируйте память, присвоенную groupWithID* указатель перед первым доступом для чтения. Все биты памяти могут быть повторно инициализированы с помощью memset функция.

#include<cstdlib>
#include<cstring>

struct group {
    char *groupFirst;
    int groupSize;
};

struct groupWithID {
    int groupID;
    char *groupFirst;
    int groupSize;
};

char* readName();
int readSize();

void createGroup(int nextAvailableID) {
    struct group *aGroup;
    struct groupWithID *aGroupWithID;
    
    aGroup = (struct group*) malloc(sizeof(struct group));
    aGroup->groupFirst = readName();
    aGroup->groupSize  = readSize();
    
    if(!aGroup) {
        /*Handle error*/
    }
    
    /* Reassign to group with ID */
    aGroupWithID = (struct groupWithID*) realloc(aGroup, sizeof(struct groupWithID));
    if(!aGroupWithID) {
        free(aGroup);
        /*Handle error*/
    }
    
    memset(aGroupWithID, 0 , sizeof(struct groupWithID));
    /* Reinitialize group */
    if(aGroupWithID -> groupSize > 0) { 
        /* ... */
    }
    
    /* ...*/
    free(aGroupWithID);
}

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

Группа: 02. Выражения (EXP)
Введенный в 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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