In the commit: rM3c1c98a43413: core: Use flexible array member if compiler has support.
The commit title was "Use of flexible array member", but my intention was actually use of offsetof to clarify the size of allocation.
In the commit: rM3c1c98a43413: core: Use flexible array member if compiler has support.
The commit title was "Use of flexible array member", but my intention was actually use of offsetof to clarify the size of allocation.
For the use case of struct arg_and_data_s in gpgme, which may allocate zero-sized ARG[], it seems that GCC 11 interprets it as an invalid use.
Moving ARG_LOCP field next to DATA, so that size of the structure can be smaller on 64-bit machine, we can see the warning again, even with the use of flexible array member.
For GCC 11, modified version of struct arg_and_data_s has an issue for x86_64.
struct arg_and_data_s
{
struct arg_and_data_s *next;
gpgme_data_t data; /* If this is not NULL, use arg below. */
int *arg_locp; /* Write back the argv idx of this argument when
building command line to this location. */
int inbound; /* True if this is used for reading from gpg. */
int dup_to;
int print_fd; /* Print the fd number and not the special form of it. */
char arg[]; /* Used if data above is not used. */
};That is, sizeof (struct arg_and_data_s) is 40, while offsetof(struct arg_and_data_s, arg) is 36. I'm afraid we have to call it a compiler problem.
t-fam.c: In function 'main':
t-fam.c:34:14: warning: array subscript 'struct arg_and_data_s[0]' is partly outside array bounds of 'unsigned char[22]' [-Warray-bounds]
34 | aad0->next = NULL;
| ^
t-fam.c:30:10: note: referencing an object of size 22 allocated by 'malloc'
30 | aad0 = malloc (offsetof (struct arg_and_data_s, arg) + 2);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t-fam.c:35:13: warning: array subscript 'struct arg_and_data_s[0]' is partly outside array bounds of 'unsigned char[22]' [-Warray-bounds]
35 | aad0->len = 2;
| ~~~~~~~~~~^~~
t-fam.c:30:10: note: referencing an object of size 22 allocated by 'malloc'
30 | aad0 = malloc (offsetof (struct arg_and_data_s, arg) + 2);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t-fam.c:36:15: warning: array subscript 'struct arg_and_data_s[0]' is partly outside array bounds of 'unsigned char[22]' [-Warray-bounds]
36 | aad0->flags = 0;
| ~~~~~~~~~~~~^~~
t-fam.c:30:10: note: referencing an object of size 22 allocated by 'malloc'
30 | aad0 = malloc (offsetof (struct arg_and_data_s, arg) + 2);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t-fam.c:37:18: warning: array subscript 'struct arg_and_data_s[0]' is partly outside array bounds of 'unsigned char[22]' [-Warray-bounds]
37 | aad0->print_fd = fd;
| ~~~~~~~~~~~~~~~^~~~
t-fam.c:30:10: note: referencing an object of size 22 allocated by 'malloc'
30 | aad0 = malloc (offsetof (struct arg_and_data_s, arg) + 2);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~I filed a bug report to GCC, with modified test case.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102151
FYI: the gcc maintainers don't agree that it is a bug. But I think Gniibe is right here. For reference Gniibe's final comment at the gcc tracker:
Niibe Yutaka 2021-09-02 02:34:38 UTC Thank you for the explanation. I understand how (current version of) GCC warns. From the viewpoint of use of structure with flexible array member, still, this could be considered as a bug of GCC, because the warning itself is irrelevant. My point is that: (1) In the test case, use of offsetof(struct arg_and_data_s, arg) is valid (I mean, no violation of language/feature). In other words, (2) Allocated space for an object of the structure may be smaller than sizeof(). There are such cases, for structure with flexible array member, because of structure alignment. (3) It seems for me that by (current version of) GCC, the fact (2) is ignored.
Let's close this bug because we have a workaround in libgcrypt 1.12.