CERT C++: EXP36-C

Не бросайте указатели в более строго выровненные типы указателей

Описание

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

Не бросайте указатели в более строго выровненные типы указателей. [1]

Примеры

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

Описание

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

Риск

Разыменование неправильно выровненного указателя имеет неопределенное поведение и может заставить вашу программу отказывать.

Фиксация

Предположим, что вы преобразовываете указатель ptr1 в ptr2. Если ptr1 указывает на буфер байтов N, и ptr2 является указателем type *, где sizeof(type) является байтами n, убедитесь, что N является целочисленным кратным n.

Смотрите примеры мер ниже.

Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Комментарии.

Пример - динамическое выделение указателей

#include <stdlib.h>

void dyn_non_align(void){
    void *ptr = malloc(13);
    long *dest;

    dest = (long*)ptr; //defect
}

В этом примере программное обеспечение повышает дефект на преобразовании ptr к long*. Динамически выделенная память о ptr, 13 байтов, не является кратным размеру dest, 4 байта. Это неточное совмещение вызывает Неправильный выделенный размер объекта для дефекта броска.

Исправление — изменяет размер указателя

Одно возможное исправление должно использовать размер указателя, который является кратным целевому размеру. В этом примере разрешите дефект путем изменения выделенной памяти 12 вместо 13.

#include <stdlib.h>

void dyn_non_align(void){
    void *ptr = malloc(12);
    long *dest;

    dest = (long*)ptr;
}

Пример - статическое выделение указателей

void static_non_align(void){
    char arr[13], *ptr;
    int *dest;

    ptr = &arr[0];
    dest = (int*)ptr; //defect
}

В этом примере программное обеспечение повышает дефект на преобразовании ptr к int* в строке 6. ptr имеет емкость памяти 13 байтов, потому что массив arr имеет размер 13 байтов. Размер dest составляет 4 байта, который не является кратным 13. Это неточное совмещение вызывает Неправильный выделенный размер объекта для дефекта броска.

Исправление — изменяет размер указателя

Одно возможное исправление должно использовать размер указателя, который является кратным целевому размеру. В этом примере разрешите дефект путем изменения размера массива arr к кратному 4.

void static_non_align(void){
    char arr[12], *ptr;
    int *dest;

    ptr = &arr[0];
    dest = (int*)ptr;
}

Пример - выделение с функцией

#include <stdlib.h>

void *my_alloc(int size) { 
    void *ptr_func = malloc(size); 
    if(ptr_func == NULL) exit(-1); 
    return ptr_func; 
}

void fun_non_align(void){
    int *dest1;
    char *dest2;

    dest1 = (int*)my_alloc(13);  //defect
    dest2 = (char*)my_alloc(13); //not a defect
}

В этом примере программное обеспечение повышает дефект на преобразовании указателя, возвращенного my_alloc(13) в int* в строке 11. my_alloc(13) возвращает указатель с динамически выделенным размером 13 байтов. Размер dest1 составляет 4 байта, который не является делителем 13. Это неточное совмещение вызывает Неправильный выделенный размер объекта для дефекта броска. В строке 12, тот же вызов функции, my_alloc(13), не вызывает дефект для преобразования в dest2 потому что размер char*, 1 байт, делителя 13.

Исправление — изменяет размер указателя

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

#include <stdlib.h>

void *my_alloc(int size) { 
    void *ptr_func = malloc(size); 
    if(ptr_func == NULL) exit(-1); 
    return ptr_func; 
}

void fun_non_align(void){
    int *dest1;
    char *dest2;

    dest1 = (int*)my_alloc(12); 
    dest2 = (char*)my_alloc(13); 
}

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

Группа: 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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