Hi!

Currently, one can have pseudo-flexible array members in unions with
[0] syntax, but it's not allowed with [] syntax.

Here's an example of how it is possible today:

struct s {
        ...

        size_t  n;
        union {
                ptrdiff_t  off[0];  // [n]; offsets from s->data.
                char       data[0];
        };
};

which is useful to have a structure with two (or really several)
consecutive flexible arrays: one of offsets, which mark the positions
of data, and another with the actual data.  Below goes an example
program, which works fine with GCC, and I believe rewriting it to
not use the union would make it less clear, since I'd need to add
casts to it.

It works thanks to [0] pseudo-flexible arrays, but it doesn't
compile with C99 flexible arrays.  And of course, [0] arrays have
issues with -fstrict-flex-arrays=3.


$ cat flexi4.c 
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct s {
        size_t     n;
        union {
                ptrdiff_t  off[0];
                char       data[0];
        };
};

int
main(void)
{
        char      *p;
        struct s  *s;

        s = malloc(offsetof(struct s, off) +
                   sizeof(ptrdiff_t) * 2 +
                   sizeof("foobar") + sizeof("baz"));

        s->n = 2;
        p = s->data + sizeof(ptrdiff_t) * s->n;

        s->off[0] = p - s->data;
        p = stpcpy(p, "foobar") + 1;
        s->off[1] = p - s->data;
        p = stpcpy(p, "baz") + 1;

        puts(s->data + s->off[0]);
        puts(s->data + s->off[1]);

        free(s);
}
$ gcc-13 -Wall -Wextra -Werror -fanalyzer \
         -fsanitize=undefined -fsanitize=address \
         -D_FORTIFY_SOURCE=3 -fstrict-flex-arrays=2 \
         flexi4.c 
$ ./a.out 
foobar
baz
$ gcc-13 -Wall -Wextra -Werror -fanalyzer \
         -fsanitize=undefined -fsanitize=address \
         -D_FORTIFY_SOURCE=3 -fstrict-flex-arrays=3 \
         flexi4.c 
$ ./a.out 
flexi4.c:27:8: runtime error: index 0 out of bounds for type 'ptrdiff_t [*]'
flexi4.c:29:8: runtime error: index 1 out of bounds for type 'ptrdiff_t [*]'
flexi4.c:32:23: runtime error: index 0 out of bounds for type 'ptrdiff_t [*]'
foobar
flexi4.c:33:23: runtime error: index 1 out of bounds for type 'ptrdiff_t [*]'
baz


Would you allow flexible array members in unions?  Is there any
strong reason to disallow them?

Currently, I get:

$ gcc-13 -Wall -Wextra -fanalyzer \
         -fsanitize=undefined -fsanitize=address \
         -D_FORTIFY_SOURCE=3 -fstrict-flex-arrays=3 \
         flexi4-true.c 
flexi4-true.c:9:28: error: flexible array member in union
    9 |                 ptrdiff_t  off[];
      |                            ^~~
flexi4-true.c:10:28: error: flexible array member in union
   10 |                 char       data[];
      |                            ^~~~


Cheers,
Alex

-- 
<http://www.alejandro-colomar.es/>
GPG key fingerprint: A9348594CE31283A826FBDD8D57633D441E25BB5

Attachment: OpenPGP_signature
Description: OpenPGP digital signature

Reply via email to