The C99 C standard [ISO/IEC 9899:19992011] introduces provides flexible array members into in the languageC language. While flexible array members are a useful addition, they need to be understood and used with care.
The following is an example of a structure that contains a flexible array member:
Code Block |
---|
struct flexArrayStruct {
int num;
int data[];
};
|
This definition means that , when allocating storage, only the first member, num
, is considered. Consequently, the result of accessing the member data
of a variable of type struct flexArrayStruct
is undefined. Rule DCL38-C. Use the correct syntax when declaring flexible array members describes the correct way to declare a struct
with a flexible array member.
...
Code Block | ||||
---|---|---|---|---|
| ||||
struct flexArrayStruct flexStruct;
size_t array_size;
size_t i;
/* Initialize array_size */
/* Initialize structure */
flexStruct.num = 0;
for (i = 0; i < array_size; i++) {
flexStruct.data[i] = 0;
}
|
The problem with this code is that the flexArrayStruct
does not actually reserve space for the integer array data; it can't because the size hasn't been specifiedsize is not specified. Consequently, while initializing the num
member to zero is allowed, attempting to write even one value into data (that is, data[0]
) is likely to overwrite memory outside of the object's bounds.
...
Code Block | ||||
---|---|---|---|---|
| ||||
struct flexArrayStruct *flexStruct;
size_t array_size;
size_t i;
/* Initialize array_size */
/* Dynamically allocate memory for the structure */
flexStruct = (struct flexArrayStruct *)malloc(
sizeof(struct flexArrayStruct) + sizeof(int) * array_size
);
if (flexStruct == NULL) {
/* Handle malloc failure */
}
/* Initialize structure */
flexStruct->num = 0;
for (i = 0; i < array_size; i++) {
flexStruct->data[i] = 0;
}
|
The data[]
member of flexStruct
can now be accessed as described in C99the C standard, Section 6.7.2.1, paragraph 1618.
Noncompliant Code Example (Copying)
...
Code Block | ||||
---|---|---|---|---|
| ||||
struct flexArrayStruct *flexStructA;
struct flexArrayStruct *flexStructB;
size_t array_size;
size_t i;
/* Initialize array_size */
/* Allocate memory for flexStructA */
/* Allocate memory for flexStructB */
/* Initialize flexStructA */
/* ... */
*flexStructB = *flexStructA;
|
The problem with this noncompliant code example is that , when the structure is copied, the size of the flexible array member is not considered, and only the first member of the structure, num
, is copied.
...
Code Block | ||||
---|---|---|---|---|
| ||||
struct flexArrayStruct *flexStructA;
struct flexArrayStruct *flexStructB;
size_t array_size;
size_t i;
/* Initialize array_size */
/* Allocate memory for flexStructA */
/* Allocate memory for flexStructB */
/* Initialize flexStructA */
/* ... */
memcpy(
flexStructB,
flexStructA,
(sizeof(struct flexArrayStruct) + sizeof(int) * array_size)
);
|
...
Code Block | ||||
---|---|---|---|---|
| ||||
void print_array(struct flexArrayStruct structP) {
size_t i;
puts("Array is: ");
for (i = 0; i < structP.num; i++) {
printf("%d", structP.data[i]);
}
puts("\n");
}
struct flexArrayStruct *structP;
size_t array_size;
size_t i;
/* initialize array_size */
/* space is allocated for the struct */
structP = (struct flexArrayStruct *)malloc(
sizeof(struct flexArrayStruct) + sizeof(int) * array_size
);
if (structP == NULL) {
/* Handle malloc failure */
}
structP->num = array_size;
for (i = 0; i < array_size; i++) {
structP->data[i] = i;
}
print_array(*structP);
|
...
Code Block | ||||
---|---|---|---|---|
| ||||
void print_array(struct flexArrayStruct *structP) {
size_t i;
puts("Array is: ");
for (i = 0; i < structP->num; i++) {
printf("%d", structP->data[i]);
}
puts("\n");
}
struct flexArrayStruct *structP;
size_t array_size;
size_t i;
/* initialize array_size */
/* space is allocated for the struct */
structP = (struct flexArrayStruct *)malloc(
sizeof(struct flexArrayStruct) + sizeof(int) * array_size
);
if (structP == NULL) {
/* Handle malloc failure */
}
structP->num = array_size;
for (i = 0; i < array_size; i++) {
structP->data[i] = i;
}
print_array(structP);
|
...
Tool | Version | Checker | Description | section|
---|---|---|---|---|
ROSE |
|
| Section | Can detect all of these. |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Bibliography
...