❦ 14 mai 2016 15:20 +0200, Cyril Bonté <cyril.bo...@free.fr> :

>>> What is the most important is to report this to the gcc maintainers so that
>>> they can fix the bug. The fix will naturally flow into the distros.
>>>
>>
>> I understand this and of course I could try to fill a bug on their side but
>> the gcc stuff is a bit out of my league.
>
> After spending some time on this, I'm now able to produce a minimal
> test case.
>
> $ gcc-6 -O2 -o debug debug.c && ./debug
> 0
> => here we have an issue, as it shouldn't be 0
>
> $ gcc-6 -O2 -DDEBUG -o debug debug.c && ./debug
> 7f000001
> 7f000001
> => Suddenly, everything works
>
> And now, what happens with this debug code when -fno-tree-sra is used ?
> $ gcc-6 -O2 -fno-tree-sra -DDEBUG -o debug debug.c && ./debug
> 7f000001
> 0
> => It still doesn't work :-( So, disabling "tree-sra" doesn't
> guarantee the right behaviour.
>
> I also attach a debug2.c example, which is also disturbing. It is the
> same code, but adds a local variable. Depending on the code order,
> strange things happen (looks like a memory alignment issue).
> For example :
> $ gcc-6 -O2 -o debug2 debug2.c && ./debug2
> 0
> fd7f0000
>
> Note : my tests were made on a Debian SID with the gcc-6 package.

I think this is an aliasing problem. You cannot have two incompatible
variables pointing at the same memory spot. It seems that now
sockaddr_storage and sockaddr_in are not compatible anymore.

#v+
struct sockaddr_storage
  {
    __SOCKADDR_COMMON (ss_);    /* Address family, etc.  */
    __ss_aligntype __ss_align;  /* Force desired alignment.  */
    char __ss_padding[_SS_PADSIZE];
  };

struct sockaddr_in
  {
    __SOCKADDR_COMMON (sin_);
    in_port_t sin_port;                 /* Port number.  */
    struct in_addr sin_addr;            /* Internet address.  */

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr) -
                           __SOCKADDR_COMMON_SIZE -
                           sizeof (in_port_t) -
                           sizeof (struct in_addr)];
  };
#v-

If I introduce this type:

#v+
struct  sockaddr_storage_universal {
        union {
                struct sockaddr_storage sas;
                struct sockaddr_in sai;
                struct sockaddr_in6 sai6;
        };
};
#v-

This works when used in place of "struct sockaddr_storage". I see the
glibc is using an union too instead of struct sockaddr or struct
sockaddr_storage. man 7 socket still says to use struct
sockaddr_storage.

Searching a bit, there is this old question on StackOverflow:
 
http://stackoverflow.com/questions/1429645/how-to-cast-sockaddr-storage-and-avoid-breaking-strict-aliasing-rules
-- 
I think we are in Rats' Alley where the dead men lost their bones.
                -- T.S. Eliot

Reply via email to