exponenta event banner

CERT C: EXP42-C правил

Не сравнивать дополняющие данные

Описание

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

Не сравнивать дополняющие данные. [1 ]

Внедрение Polyspace

Эта проверка проверяет сравнение дополняющих данных в памяти.

Примеры

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

Проблема

Сравнение данных заполнения в памяти происходит при использовании memcmp функция для сравнения двух структур в целом. В процессе сравниваются бессмысленные данные, хранящиеся в заполнении структуры.

Например:

typedef struct structType {
    char member1;
    int member2;
    //...
}myStruct;

myStruct var1;
myStruct var2;
//...
if(memcmp(&var1,&var2,sizeof(var1))) 
{//...}

Риск

Если элементы структуры имеют различные типы данных, компилятор вводит дополнительное заполнение для выравнивания данных в памяти. Пример заполнения см. в разделе Higher Estimate of Local Variable Size.

Содержимое этих дополнительных байтов заполнения не имеет смысла. Стандарт C допускает неопределенное содержание этих байтов, давая различным компиляторам свободу для реализации собственного заполнения. При выполнении побайтового сравнения структур с memcmp, вы сравниваете даже бессмысленные данные, хранящиеся в заполнении. Можно сделать ложный вывод о том, что две структуры данных не равны, даже если их соответствующие элементы имеют одинаковое значение.

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

Вместо сравнения двух структур за одну попытку сравните элементы структур по элементам.

Для эффективного кода запишите функцию, которая выполняет элемент сравнения по элементу. Эта функция используется для сравнения двух структур.

Вы можете использовать memcmp для побайтового сравнения структур, только если известно, что структуры не содержат заполнения. Как правило, для предотвращения заполнения используются определенные атрибуты или прагматики, такие как #pragma pack. Однако эти атрибуты или прагматики поддерживаются не всеми компиляторами и делают реализацию кода зависимой. Если структуры содержат битовые поля, использование этих атрибутов или прагматик не может предотвратить заполнение.

Пример - Структуры по сравнению с memcmp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define fatal_error() abort()

typedef struct s_padding
{
    char c;            
    int i;
    unsigned int bf1:1;    
    unsigned int bf2:2;
    unsigned char buffer[20];
} S_Padding ;

/* Function that guarantees safe access to the input memory */
extern int trusted_memory_zone(void *ptr, size_t sz); 

int func(const S_Padding *left, const S_Padding *right)
{

    if (!trusted_memory_zone((void *)left, sizeof(S_Padding)) ||
        !trusted_memory_zone((void *)right, sizeof(S_Padding))) {
        fatal_error();
    }

    if (0 == memcmp(left, right, sizeof(S_Padding))) 
    {
        return 1;
    }
    else
        return 0;
}

В этом примере: memcmp сравнивает по байтам две структуры, которые left и right указывает на. Даже если значения, сохраненные в элементах структуры, одинаковы, сравнение может показать неравенство, если бессмысленные значения в заполняющих байтах не совпадают.

Исправление - Сравнение элементов структур по членам

Одной из возможных корректировок является сравнение отдельных элементов структуры.

Примечание

Можно сравнить массивы целиком с помощью memcmp. Все элементы массива имеют одинаковый тип данных. Заполнение байтов не требуется для хранения массивов.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define fatal_error() abort()

typedef struct s_padding
{
    char c;         
    int i;
    unsigned int bf1:1;    
    unsigned int bf2:2;
    unsigned char buffer[20];
} S_Padding ;

/* Function that guarantees safe access to the input memory */
extern int trusted_memory_zone(void *ptr, size_t sz); 

int func(const S_Padding *left, const S_Padding *right)
{
    if (!trusted_memory_zone((void *)left, sizeof(S_Padding)) ||
        !trusted_memory_zone((void *)right, sizeof(S_Padding))) {
        fatal_error();
    }

    return ((left->c == right->c) &&                
            (left->i == right->i) &&
            (left->bf1 == right->bf1) &&
            (left->bf2 == right->bf2) &&
            (memcmp(left->buffer, right->buffer, 20) == 0)); 
}

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

Группа: Правило 03. Выражения (EXP)
Представлен в R2019a

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

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

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