...
Flexible array members are defined in subclause 6.7.2.1 of paragraph 18 of the C Standard [ISO/IEC 9899:2011] as follows:
...
- The incomplete array type must be the last element within the structure.
- There cannot be an array of structures that contain flexible array members.
- Structures that contain a flexible array member cannot be used as a member in the middle of another structure.
- The structure must contain at least one named member in addition to the flexible array member.
MEM33-C. Allocate and copy structures containing flexible array members dynamically describes how to allocate and copy structures containing flexible array members.
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdlib.h> /* For malloc() and size_t */ struct flexArrayStruct { int num; int data[1]; }; /* ... */ void func(size_t array_size; size_t i; void func(void) { /* Initialize array_size */ /* Space is allocated for the struct */ struct flexArrayStruct *structP = (struct flexArrayStruct *) malloc(sizeof(struct flexArrayStruct) + sizeof(int) * (array_size - 1)); if (structP == NULL) { /* Handle malloc failure */ } structP->num = 0array_size; /* * Access data[] as if it had been allocated * as data[array_size]. */ for (size_t i = 0; i < array_size; i++i) { structP->data[i] = 1; } } |
The problem with using this approach is that the behavior is undefined when accessing other than the first element of data. (See subclause 6.5.6 of the C Standard [ISO/IEC 9899:2011].) Consequently, the compiler can generate code that does not return the expected value when accessing the second element of data.
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdlib.h> /* For malloc() and size_t */ struct flexArrayStruct{ int num; int data[]; }; /* ... */ void func(size_t array_size; size_t i; void func(void) { /* Initialize array_size */ /* Space is allocated for the struct */ struct flexArrayStruct *structP = (struct flexArrayStruct *) malloc(sizeof(struct flexArrayStruct) + sizeof(int) * array_size); if (structP == NULL) { /* Handle malloc failure */ } structP->num = 0array_size; /* * Access data[] as if it had been allocated * as data[array_size]. */ for (size_t i = 0; i < array_size; i++i) { structP->data[i] = 1; } } |
This compliant solution allows the structure to be treated as if it had declared the member data[]
to be data[array_size]
in a manner that conforms to the C Standard. Note that Microsoft Visual Studio implements support for flexible array members, but some versions (such as MSVC 11) warn that this is a nonstandard extension.
Risk Assessment
Failing to use the correct syntax can result in undefined behavior, although the incorrect syntax will work on most implementations.
...
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
CERT C Secure Coding Standard | MEM33-C. Allocate and copy structures containing flexible array members dynamically |
Bibliography
[ISO/IEC 9899:2011] | Subclause 6.5.6, "Additive Operators" Subclause 6.7.2.1, "Structure and Union Specifiers" |
[McCluskey 2001] | "Flexible Array Members and Designators in C9X" |
...