Hi Richard, On 2023-08-14 08:41, Richard Biener wrote: > On Fri, Aug 11, 2023 at 8:30 PM Alejandro Colomar via Gcc > <[email protected]> wrote:
[...]
>> 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])?).
You may be confusing sizeof(struct contains_fam) with sizeof(fam[n]).
Yes, the second is necessary for allocation, but the first is not. Well,
it is valid for allocation but only because allocating extra bytes is not
a problem.
The size of a flexible structure is calculated as the sum of the offset
of the fam, and the size of the fam. The size of the structure has nothing
to do.
struct s {
int i;
char c;
char fam[];
} s;
size = offsetof(struct s, fam) + sizeof("foobar")); // OK: 12 B
size = sizeof(struct s) + sizeof("foobar")); // NOK: 15 B; wastes bytes
^~~~ problem here.
>
> Iff we want to diagnose anything then possibly a computation that looks like
> a size computation but that's actually smaller than required,
It's actually the other way around. The problem is that the computation may
give a value larger than the expected one. This can be usually a benign bug
and nothing bad will happen. But when a programmer relies on that size for
reading or writing, which I've seen happen, you better make sure that the
structure has no padding, or you'll be reading/writing at `fam + padding`.
Example, using the allocation above:
strcpy((char *) s + sizeof(struct s), "foobar"); // NOK, writes after
padding
puts(s->fam); // OK, reads the fam, but surprise
// Unpredictable; prints 3 uninitialized bytes, then (if no previous
'\0') "foobar"
strcpy(s->fam, "foobar"); // OK, writes at the fam
puts((char *) s + sizeof(struct s)); // NOK, reads after padding
// prints: "bar"
strcpy(s->fam, "foobar"); // OK
puts((char *) s + offsetof(struct s, fam)); // OK; with offsetof,
equivalent to s->fam
// prints: "foobar"
strcpy((char *) s + offsetof(struct s, fam), "foobar"); // Also OK
puts(s->fam); // OK
// prints: "foobar"
> but
> other than that - what
> would you suggest to fix such reported warnings?
To fix the warnings, replace all invocations of `sizeof(struct contains_fam)`
by `offsetof(struct contains_fam, fam)`.
Cheers,
Alex
--
<http://www.alejandro-colomar.es/>
GPG key fingerprint: A9348594CE31283A826FBDD8D57633D441E25BB5
OpenPGP_signature
Description: OpenPGP digital signature
