http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52944

--- Comment #3 from Richard Guenther <rguenth at gcc dot gnu.org> 2012-04-12 
15:28:10 UTC ---
(In reply to comment #2)
> if you look at the tftp example, you'd see that your proposed struct does not
> work.  the protocol needs two flexible array members at different starting
> points.

Ah, indeed.  Now when inspecting your description closer.

---
with tftp, the packet is described by:
struct tftphdr {
    short opcode;
    union {
        unsigned short tu_block;
        short tu_code;
        char tu_stuff[0];
    };
    char th_data[];
};

when opcode is 1, the rest of the packet is a C string.  i.e. the buffer:
    char x[] = { 1, 0, 'f', 'i', 'l', 'e', '\0', };
    opcode = 1, tu_stuff = "file"

when opcode is 3 though, the tu_block field will be a number, and the rest of
the data will be in th_data.  i.e. the buffer:
    char x[] = { 2, 0, 3, 0, <8KiB>, };
    opcode = 2, tu_block = 3, th_data = 8KiB
---

So

struct tftphdr {
    short opcode;
    union {
        struct opcode_3 {
           unsigned short tu_block;
           char th_data[];
        } opcode3;
        short tu_code;
        char tu_stuff[0];
    };
};

would work.  At least

struct stct {
    int i;
    union {
        struct {
            short k;
            char tail[];
        } x;
        char buf[0];
    };
};
char buf[100];
main()
{
  struct stct *foo = (void *)buf;
  printf("%i\n", __builtin_object_size(foo->buf, 1));
  printf("%i\n", __builtin_object_size(foo->x.tail, 1));
}

produces the expected 96, 94 values?

> the 96 isn't conservative in this case, it's correct.  i declared a buffer of
> 100 bytes, so buf[0] can cover 96 bytes (as the leading integer is 32bits).  
> is
> there a "simplish" patch that could be backported to the 4.5/4.6 branches for
> that ?

No, and it's only because optimization triggers and we get to see buf[] here.
Otherwise you'd get still zero.

> thinking a bit more, the requirements can probably be pulled off with more
> anonymous unions/structs like so:
> 
> struct tftphdr {
>     short opcode;
>     union {
>         struct {
>             union {
>                 unsigned short tu_block;
>                 short tu_code;
>             };
>             char tu_data[0];
>         };
>         char tu_stuff[0];
>     } __attribute__ ((__packed__));
> } __attribute__ ((__packed__));

I don't see how this would avoid the issue for __builtin_object_size
(foo->...tu_data) though.

Reply via email to