On 2023-08-14 19:11, Alejandro Colomar wrote:
> Hi Martin,
> 
> On 2023-08-14 18:49, Martin Uecker wrote:
>> Am Montag, dem 14.08.2023 um 12:21 +0200 schrieb Alejandro Colomar:
> [...]
> 
>>> Would you mind chiming in to this question?:
>>> <https://software.codidact.com/posts/287754>
>>
>> Unclear. It is probably UB by omission.
> 
> Agree.
> 
>>  But this is possibly
>> different from the FAM case.
> 
> I don't think I agree on this.  To me it really looks like the same thing.
> BTW, there was a mention there to the FAM case in a comment:
> <https://software.codidact.com/comments/thread/7169#comment-21254>
> 
>>
>> I any case, I am not so concerned about the whether this UB, 
>> but that a programmer might do:
>>
>> struct s = { .. }
>> struct s* p = malloc(...)
>> memcpy(p, &s, sizeof s); // copy header. 
> 
> That's (or could be) a bug, and just another manifestation of why
> sizeof(s) is wrong.  Let's see a couple of ways how this can go wrong:
> 
> 
> $ cat memcpy.c 
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> 
> struct s {
>       int   i;
>       char  c;
>       char  fam[];
> };
> 
> struct h {
>       int   i;
>       char  c;
> };
> 
> int
> main(void)
> {
>       char      *f;
>       struct h  h = { .i = 42, .c = 3 };
>       struct s  *p;
> 
>       p = malloc(sizeof(struct s) + sizeof("foobar"));
> 
>       strcpy(p->fam, "foobar");
>       /*
>        * since we're copying the header, it shouldn't matter if we
>        * copy it after copying the fam itself, no?  They're at
>        * different locations... or are they?
>        */
>       memcpy(p, &h, sizeof(struct s));

But if you did here

        memcpy(p, &h, offsetof(struct s, fam));

>       puts(p->fam);
>       free(p);
> 
>       p = malloc(sizeof(struct s) + sizeof("foobar"));
> 
>       f = mempcpy(p, &h, sizeof(struct s));

and here

        f = mempcpy(p, &h, offsetof(struct s, fam));

Then it magically works as expected:

$ ./a.out 
foobar
foobar


>       /*
>        * We could reuse the pointer from mempcpy(3) to get the location
>        * of just after the header, right?  Heh.
>        */
>       strcpy(f, "foobar");
>       puts(p->fam);
>       free(p);
> }
> $ cc -Wall -Wextra memcpy.c -D_GNU_SOURCE
> $ ./a.out 
> 
> 
> $
> 
> 
> Cheers,
> Alex
> 

-- 
<http://www.alejandro-colomar.es/>
GPG key fingerprint: A9348594CE31283A826FBDD8D57633D441E25BB5

Attachment: OpenPGP_signature
Description: OpenPGP digital signature

Reply via email to