Flexible array members are a special type of array where the last element of a structure with more than one named member has an incomplete array type; that is, the size of the array is not specified explicitly within the structure. A variety of different syntaxes have been used for declaring flexible array members. For C99-compliant implementations, use the syntax guaranteed valid by C99.
Non-Compliant Code Example
In the following non-compliant code, an array of size 1 is declared, but when the structure itself is instantiated, the size computed for malloc()
is modified to take into account the full size of the dynamic array.
struct flexArrayStruct { int num; int data[1]; }; /* ... */ /* Space is allocated for the struct */ struct flexArrayStruct *structP = malloc(sizeof(struct flexArrayStruct) + sizeof(int) * (ARRAY_SIZE - 1)); if (!structP) { /* handle malloc failure */ } structP->num = SOME_NUMBER; /* Access data[] as if it had been allocated as data[ARRAY_SIZE] */ for (i = 0; i < ARRAY_SIZE; i++) { structP->data[i] = i; }
However, in this non-compliant code example, the only member that is guaranteed to be valid, by strict C99 definition, is structP->data[0]
. Consequently, for all i > 0
, the results of the assignment are undefined.
Compliant Solution
This compliant solution uses the flexible array member to achieve a dynamically sized structure.
struct flexArrayStruct{ int num; int data[]; }; /* ... */ /* Space is allocated for the struct */ struct flexArrayStruct *structP = malloc(sizeof(struct flexArrayStruct) + sizeof(int) * ARRAY_SIZE); if (!structP) { /* handle malloc failure */ } structP->num = SOME_NUMBER; /* Access data[] as if it had been allocated as data[ARRAY_SIZE] */ for (i = 0; i < ARRAY_SIZE; i++) { structP->data[i] = i; }
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 C99 standard.
However, some restrictions apply:
- The incomplete array type must be the last element within the structure.
- You cannot have an array of structure if the structure contains flexible array members.
- Structures that contain a flexible array member cannot be used as a member in the middle of another structure.
- You cannot apply the
sizeof
operator to a flexible array.
Risk Assessment
Although the non-compliant approach results in undefined behavior, it does work under most architectures.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
MEM33-C |
1 (low) |
1 (unlikely) |
3 (low) |
P3 |
L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[McCluskey 01]] ;login:, July 2001, Volume 26, Number 4
[[ISO/IEC 9899-1999]] Section 6.7.2.1, "Structure and union specifiers"