On Fri, Aug 11, 2023 at 8:30 PM Alejandro Colomar via Gcc
<gcc@gcc.gnu.org> wrote:
>
> Hi!
>
> Structures with flexible array members have restrictions about being
> used in arrays or within other structures, as the size of the enclosing
> aggregate type would be... inconsistent.
>
> In general, sizeof(flexible_struct) is a problematic thing that rarely
> means what programmers think it means.  It is not the size of the
> structure up to the flexible array member; or expressed using C,
> the following can be true:
>
>         sizeof(s) != offsetof(s, fam)
>
> See the program at the bottom that demonstrates how this is problematic.
>
> It's true that if one uses
>
>         malloc(offseof(s, fam) + sizeof_member(s, fam[0]) * N);
>
> and N is very small (0 or 1 usually), the allocation would be smaller
> than the object size, which for GCC seems to be fine, but I'm worried the
> standard is not clear enough about its validity[1].
>
> [1]: <https://software.codidact.com/posts/287754>
>
> To avoid having UB there, pedantically one would need to call
>
>         malloc(MAX(sizeof(s), offseof(s, fam) + sizeof_member(s, fam[0]) * 
> N));
>
> But I think that's the only correct use of sizeof() with structures
> containing flexible array members.  So it seems sizeof() by itself is
> a valid thing, but when adding it to something else to get the total size,
> or doing any arithmetic with it, that's dubious code.
>
> How about some -Wfam-sizeof-arithmetic that would not warn about taking
> sizeof(s) but would warn if that sizeof is used in any arithmetic?

There are probably many ways sizeof() plus arithmetic can yield a correct
size for allocation.  After all _all_ uses of FAM requires allocation
and there's
no convenient standard way of calculating the required size (sizeof
(fam-type[n])?).

Iff we want to diagnose anything then possibly a computation that looks like
a size computation but that's actually smaller than required, but
other than that - what
would you suggest to fix such reported warnings?

Richard.

> Cheers,
> Alex
>
> ---
>
> $ cat off.c
> #include <err.h>
> #include <stddef.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
>
> struct s {
>         int   i;
>         char  c;
>         char  fam[];
> };
>
>
> static inline void *xmalloc(size_t size);
>
>
> int
> main(void)
> {
>         char      *p;
>         struct s  *s;
>
>         printf("sizeof: %zu\n", sizeof(struct s));
>         printf("offsetof: %zu\n", offsetof(struct s, fam));
>
>         puts("\nWith sizeof():");
>
>         s = xmalloc(sizeof(struct s) + sizeof("Hello, sizeof!"));
>         strcpy(s->fam, "Hello, sizeof!");
>         p = (char *) s + sizeof(struct s);
>         puts(p);
>         free(s);
>
>         puts("\nWith offsetof(3):");
>
>         s = xmalloc(offsetof(struct s, fam) + sizeof("Hello, offsetof!"));
>         strcpy(s->fam, "Hello, offsetof!");
>         p = (char *) s + offsetof(struct s, fam);
>         puts(p);
>         free(s);
>
>         exit(EXIT_SUCCESS);
> }
>
>
> static inline void *
> xmalloc(size_t size)
> {
>         void  *p;
>
>         p = malloc(size);
>         if (p == NULL)
>                 err(EXIT_FAILURE, "malloc");
>         return p;
> }
> $ gcc-13 -Wall -Wextra -Wpadded -fanalyzer off.c
> off.c:12:1: warning: padding struct size to alignment boundary with 3 bytes 
> [-Wpadded]
>    12 | };
>       | ^
>
>
> The only warning I know that is triggered in the code above is -Wpadded,
> which is related to this problem, but I think there should be something
> to warn about sizeof() in this context.
>
>
> --
> <http://www.alejandro-colomar.es/>
> GPG key fingerprint: A9348594CE31283A826FBDD8D57633D441E25BB5

Reply via email to