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 standard, "There may be unnamed padding within a structure object, but not at its beginning." [[ISO/IEC 9899-1999]].
This is often referred to as 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.
Non-Compliant Code Example
This non-compliant code example assumes that the size of struct buffer
is equal to the sizeof(size_t) + (sizeof(char) * 50)
, which may not be the case [[Dowd]]. The size of struct buffer
may actually be a larger due to structure padding.
struct buffer { size_t size; char buffer[50]; }; ... void func(struct buffer *buf) { /* assuming sizeof(size_t) is 4, sizeof(size_t)+sizeof(char)*50 equals 54 */ struct buffer *buf_cpy = malloc(sizeof(size_t)+(sizeof(char)*50)); if (buf_cpy == NULL) { /* Handle malloc() error */ } ... /* with padding, sizeof(struct buffer) may be greater than 54, causing a small amount of data to be written outside the bounds of the memory allocated */ memcpy(buf_cpy, buf, sizeof(struct buffer)); }
Compliant Solution
Accounting for structure padding prevents these types of errors.
struct buffer { size_t size; char buffer[50]; }; ... void func(struct buffer *buf) { struct buffer *buf_cpy = malloc((sizeof(struct buffer)); if (buf_cpy == NULL) { /* Handle malloc() error */ } ... memcpy(buf_cpy, buf, sizeof(struct buffer)); }
Risk Assessment
Failure to correctly determine the size of a structure can lead to subtle logic errors and incorrect calculations.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
EXP03-A |
2 (medium) |
1 (unlikely) |
1 (high) |
P2 |
L3 |
References
[[Dowd 06]] Chapter 6, "C Language Issues" (Structure Padding 284-287)
[[ISO/IEC 9899-1999]] Section 6.7.2.1, "Structure and union specifiers"