Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The size of a structure is not always equal to the sum of the sizes of its members. According to Section 6.7.2.1 of the C99 C standard, "There may be unnamed padding within a structure object, but not at its beginning" [ISO/IEC 9899:19992011].

This is often referred to as often called structure padding. Structure members are arranged in memory as they are declared in the program text. Padding may be added to the structure to ensure the structure is properly aligned in memory. Structure padding allows for faster member access on many architectures.

Rearranging the fields in a struct can change the size of the struct. It is possible to minimize padding anomalies if the fields are arranged in such a way that fields of the same size are grouped together.

Padding is also referred to as also called struct member alignment. Many compilers provide a flag that controls how the members of a structure are packed into memory. Modifying this flag may cause the size of the structures to vary. Most compilers also include a keyword that removes all padding; the resulting structures are referred to as are called packed structures. Overriding the default behavior is often unwise because it leads to interface compatibility problems (the nominally same struct has its layout interpreted differently in different modules).

...

Code Block
bgColor#FFcccc
langc

enum { buffer_size = 50 };

struct buffer {
  size_t size;
  char bufferC[buffer_size];
} buff;

/* ... */

void func(const struct buffer *buf) {

  /*
   * Incorrectly assumes sizeof(struct buffer) =
   * sizeof(size_t) + sizeof(buff.bufferC) 
   */
  struct buffer *buf_cpy = (struct buffer *)malloc(
    sizeof(size_t) + sizeof(buff.bufferC)
  );

  if (buf_cpy == NULL) {
    /* Handle malloc() error */
  }

  /*
   * With padding, sizeof(struct buffer) may be greater than
   * sizeof(size_t) + sizeof(buff.bufferC), causing some data  
   * to be written outside the bounds of the memory allocated.
   */
  memcpy(buf_cpy, buf, sizeof(struct buffer));

  /* ... */

  free(buf_cpy);
}

...

Code Block
bgColor#ccccff
langc

enum { buffer_size = 50 };

struct buffer {
  size_t size;
  char bufferC[buffer_size];
} buff;

/* ... */

void func(const struct buffer *buf) {

  struct buffer *buf_cpy = 
    (struct buffer *)malloc(sizeof(struct buffer));

  if (buf_cpy == NULL) {
    /* Handle malloc() error */
  }

  /* ... */

  memcpy(buf_cpy, buf, sizeof(struct buffer));

  /* ... */

  free(buf_cpy);
}

...

LDRA tool suite

Tool

Version

Checker

Description

Section
Include Page
LDRA_V
LDRA_V
section

400 S
578 S

section

Fully

Implemented

implemented

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

...

CERT C++ Secure Coding Standard: EXP03-CPP. Do not assume the size of a class or struct is the sum of the sizes of its members

ISO/IEC 9899:19992011 Section 6.7.2.1, "Structure and union specifiers"

...

[Dowd 2006] Chapter 6, "C Language Issues" (Structure Padding 284-287, pp. 284–287)
[Sloss 2004] Section 5.7, "Structure Arrangementarrangement"

...