Am Montag, dem 14.08.2023 um 11:51 +0200 schrieb Alejandro Colomar via Gcc:
> Hi Richard,
> 
> On 2023-08-14 08:41, Richard Biener wrote:
> > On Fri, Aug 11, 2023 at 8:30 PM Alejandro Colomar via Gcc
> > <gcc@gcc.gnu.org> 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.
> 

The first formula may give a result smaller than sizeof(struct s), so
could also be dangerous.

Martin



> > 
> > 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
> 


Reply via email to