ПроблемаУтечка информации через заполнение структуры происходит, когда вы не инициализируете заполнение данных структуры или объединения перед передачей его через контур. Компилятор добавляет заполнение байтов в структуру или объединение, чтобы гарантировать правильное выравнивание памяти его представителей. Битовые поля модулей могут также иметь биты заполнения.
Утечка информации через заполнение конструкции вызывает дефект, когда:
Вы вызываете ненадежную функцию со структурой или аргументом типа указателя объединения, содержащим неинициализированные данные заполнения.
Все внешние функции считаются ненадежными.
Вы копируете или назначаете структуру или объединение, содержащее неинициализированные данные заполнения, ненадежному объекту.
Все внешние структуры или объекты объединения, выходные параметры всех внешне связанных функций и обратный указатель всех внешних функций считаются ненадежными объектами.
РискБайты заполнения переданной структуры или объединения могут содержать конфиденциальную информацию, к которой может получить доступ ненадежный источник.
ЗафиксироватьПредотвратите сложение байтов заполнения для выравнивания памяти при помощи pack
прагма или атрибут, поддерживаемые вашим компилятором.
Явное объявление и инициализация заполнения байтов как полей в структуре или объединении.
Явное объявление и инициализация битовых полей, соответствующих битам заполнения, даже если вы используете pack
прагма или атрибут, поддерживаемые вашим компилятором.
Пример - Структура с заполненными байтами, переданными во внешнюю функцию#include <stddef.h>
#include <stdlib.h>
#include <string.h>
typedef struct s_padding
{
/* Padding bytes may be introduced between
* 'char c' and 'int i'
*/
char c;
int i;
/*Padding bits may be introduced around the bit-fields
* even if you use "#pragma pack" (Windows) or
* __attribute__((__packed__)) (GNU)*/
unsigned int bf1:1;
unsigned int bf2:2;
unsigned char buffer[20];
} S_Padding ;
/* External function */
extern void copy_object(void *out, void *in, size_t s);
void func(void *out_buffer)
{
/*Padding bytes not initialized*/
S_Padding s = {'A', 10, 1, 3, {}};
/*Structure passed to external function*/
copy_object((void *)out_buffer, (void *)&s, sizeof(s));
}
void main(void)
{
S_Padding s1;
func(&s1);
}
В этом примере структура s1
может иметь байты заполнения между char c
и int i
представителей. Битовые поля модулей структуры могут также содержать биты заполнения. Содержимое заполняющих байтов и бит доступно ненадежному источнику при s1
передается в func
.
Коррекция - Использование pack
Прагма для предотвращения заполнения байтовОдна возможная коррекция в Microsoft® Визуальная студия® - использовать #pragma pack()
чтобы предотвратить заполнение байтов между представителями структуры. Чтобы предотвратить заполнение бит в битовых полях s1
, явным образом объявить и инициализировать битовые поля, даже если вы используете #pragma pack()
.
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#define CHAR_BIT 8
#pragma pack(push, 1)
typedef struct s_padding
{
/*No Padding bytes when you use "#pragma pack" (Windows) or
* __attribute__((__packed__)) (GNU)*/
char c;
int i;
unsigned int bf1:1;
unsigned int bf2:2;
/* Padding bits explicitely declared */
unsigned int bf_filler : sizeof(unsigned) * CHAR_BIT - 3;
unsigned char buffer[20];
}
S_Padding;
#pragma pack(pop)
/* External function */
extern void copy_object(void *out, void *in, size_t s);
void func(void *out_buffer)
{
S_Padding s = {'A', 10, 1, 3, 0 /* padding bits */, {}};
copy_object((void *)out_buffer, (void *)&s, sizeof(s));
}
void main(void)
{
S_Padding s1;
func(&s1);
}