Main Content

Information leak via structure padding

Padding bytes can contain sensitive information

Description

This checker is deactivated in a default Polyspace® as You Code analysis. See Checkers Deactivated in Polyspace as You Code Analysis (Polyspace Access).

This defect occurs when you do not initialize the padding data of a structure or union before passing it across a trust boundary. A compiler adds padding bytes to the structure or union to ensure a proper memory alignment of its members. The bit-fields of the storage units can also have padding bits.

Information leak via structure padding raises a defect when:

  • You call an untrusted function with structure or union pointer type argument containing uninitialized padding data.

    All external functions are considered untrusted.

  • You copy or assign a structure or union containing uninitialized padding data to an untrusted object.

    All external structure or union objects, the output parameters of all externally linked functions, and the return pointer of all external functions are considered untrusted objects.

Risk

The padding bytes of the passed structure or union might contain sensitive information that an untrusted source can access.

Fix

  • Prevent the addition of padding bytes for memory alignment by using the pack pragma or attribute supported by your compiler.

  • Explicitly declare and initialize padding bytes as fields within the structure or union.

  • Explicitly declare and initialize bit-fields corresponding to padding bits, even if you use the pack pragma or attribute supported by your compiler.

Examples

expand all

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

In this example, structure s1 can have padding bytes between the char c and int i members. The bit-fields of the storage units of the structure can also contain padding bits. The content of the padding bytes and bits is accessible to an untrusted source when s1 is passed to func.

Correction — Use pack Pragma to Prevent Padding Bytes

One possible correction in Microsoft® Visual Studio® is to use #pragma pack() to prevent padding bytes between the structure members. To prevent padding bits in the bit-fields of s1, explicitly declare and initialize the bit-fields even if you use #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 explicitly 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);
}

Result Information

Group: Security
Language: C | C++
Default: Off
Command-Line Syntax: PADDING_INFO_LEAK
Impact: Low

Version History

Introduced in R2018a