Some Name
Some Name

Reputation: 9521

Flexible array member of unnamed struct

Consider the following example:

typedef struct test_flex_arr{
    size_t sz;
    struct {
        int i;
        const char *path;
    } info[];
} tfa;

int main(void){
    size_t sz = 100;
    tfa *ptr = malloc(sizeof *ptr + sizeof (*((tfa*) NULL)).info[sz]);
    ptr->info[99].i = 10;
    printf("%d\n", ptr->info[99].i); //prints 10
}

DEMO

I expected this program to crash but it runs just fine. As specified 6.5.3.4(p2):

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant

The type of the operand of sizeof ((*((tfa*) NULL)).info)[sz] is variable length array so the operand should be evaluated. But evaluation of the operand means derefencing NULL which I expected to lead to crash.

Is the behavior of the code well defined?

Upvotes: 1

Views: 159

Answers (1)

Barmar
Barmar

Reputation: 780818

(*((tfa*) NULL)).info[sz] is not a variable length array type, because (*((tfa*) NULL)).info is not a type.

So it's treating that as an ordinary expression, referring to the sz element of the array (*((tfa*) NULL)).info. Per the quoted specification, this is not evaluated, so the fact that it dereferences NULL doesn't cause undefined behavior. It simply returns the size of the array element, which is not dependent on the location of the array or the index. That's why it compiles without warning and doesn't crash.

But this doesn't produce the desired result. You're only getting the size of one element of the array, not the sz elements that you actually need to allocate space for. You need to multiply the size of an element by the number of elements. So use

tfa *ptr = malloc(sizeof *ptr + sz * sizeof ptr->info[0]);

Upvotes: 8

Related Questions