Memory comparison of padding data

memcmp сравнивает данные, хранящиеся в заполнении структуры

Описание

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

Для образца:

struct structType {
    char member1;
    int member2;
    .
    .
};

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

Риск

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

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

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

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

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

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

Примеры

расширить все

#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)); 
}

Информация о результатах

Группа: Программирование
Язык: C | C++
По умолчанию: On для рукописного кода, off для сгенерированного кода
Синтаксис командной строки: MEMCMP_PADDING_DATA
Влияние: Средний
ИДЕНТИФИКАТОР CWE: 188
Введенный в R2017a