exponenta event banner

CERT C: Rec. MEM02-C

Немедленное приведение результата вызова функции выделения памяти в указатель на назначенный тип

Описание

Определение правила

Немедленно приведите результат вызова функции выделения памяти в указатель на назначенный тип [1 ].

Внедрение Polyspace

Эта проверка проверяет неверный размер выделенного объекта для приведения.

Примеры

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

Проблема

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

Риск

Переопределение смещенного указателя имеет неопределенное поведение и может привести к аварийному завершению программы.

Зафиксировать

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

См. примеры исправлений ниже.

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

Пример - Динамическое распределение указателей
#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); 
}

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

Группа: Rec. 08. Управление памятью (MEM)
Представлен в R2019a

[1] Данное программное обеспечение было создано компанией MathWorks и включает в себя следующие компоненты: «Веб-сайт SEI CERT-C», © 2017 Университет Карнеги-Меллон, веб-сайт SEI CERT-C + + © 2017 Университет Карнеги-Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги-Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

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