The size of a structure is not always equal to the sum of the sizes of its members. Section Subclause 6.7.2.1 of the C Standard states, "There may be unnamed padding within a structure object, but not at its beginning" [ISO/IEC 9899:2011].
This unnamed padding is 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.
...
Code Block | ||||
---|---|---|---|---|
| ||||
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) + (buffer_size * sizeof(buff.bufferCchar) /* 1 */) ); 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); } |
...
Accounting for structure padding prevents these types of errors.:
Code Block | ||||
---|---|---|---|---|
| ||||
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);
}
|
...
Failure to correctly determine the size of a structure can lead to subtle logic errors and incorrect calculations, the effects of which can lead to abnormal program termination, memory corruption, or execution of arbitrary code.
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
EXP03-C |
High |
Unlikely |
High |
P3 | L3 |
Automated Detection
Tool | Version | Checker | Description |
---|
Astrée |
|
|
|
400 S
578 S
Fully implemented
Supported: Astrée reports accesses outside the bounds of allocated memory. | |||||||||
Helix QAC |
| C0697 | |||||||
LDRA tool suite |
| 578 S | Enhanced enforcement |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
SEI CERT C++ |
Coding Standard | VOID EXP03-CPP. Do not assume the size of a class or struct is the sum of the sizes of its members |
Bibliography
[Dowd 2006] | Chapter 6, "C Language Issues" ("Structure Padding," pp. 284–287) |
[ISO/IEC 9899:2011] |
Subclause 6.7.2.1, "Structure and Union Specifiers" | |
[Sloss 2004] | Section 5.7, "Structure Arrangement" |
...
...