2

In the function

size_t csps_socket_read(csps_socket_t *s, csps_packet_wrapper_t *packet, size_t sz)

I get the warning: "dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]" on the following line:

packet_size = ((csps_packet_full_header_t *)s->receive_mem)->size + header_size;

If I rewrite like this:

csps_packet_full_header_t *packet_full_header = (csps_packet_full_header_t *)s->receive_mem;
packet_size = packet_full_header->size + header_size;

I get no warning. Why? Is the problem still there but gcc can't see it?

Here's the structs involved:

typedef struct csps_socket_t_
{
    void*       fp;
    bool        open;
    uint8_t     receive_mem[CSPS_SOCKET_MEM];
    uint32_t    receive_index;
} csps_socket_t;

typedef struct ATTR_PACKED csps_packet_full_header_t_
{
    uint8_t version:4;
    uint8_t pclass:4;
    uint8_t ch:1;
    uint8_t reserved:7;
    uint16_t size;
    uint16_t sequence;
    uint16_t checksum;
    uint8_t src[8];
    uint8_t dst[8];
} csps_packet_full_header_t;
kejsarn
  • 75
  • 4
  • 3
    Yes, the problem is still there, but it seems that GCC loses track when you use an intermediate variable. Your code has undefined behaviour and might crash under various circumstances, or might not; it also depends on the Also the layout of bitfields is very much implementation defined. Also, the alignment of `receive_mem` needs to be checked - if the uint16_t members are misaligned, this might cause crashes – Antti Haapala -- Слава Україні Apr 25 '17 at 07:53
  • 1
    I recommend using `memcpy`, as in this answer: http://stackoverflow.com/q/17789928 You can see that under any optimization level, the compiler is able to understand it as type-punning and omit the actual memory copy. https://godbolt.org/g/r6VoO0 – ephemient Apr 25 '17 at 08:28
  • @AnttiHaapala Please note that OP is asking about problem in GCC, not how to rewrite the code to avoid UB. – yugr Apr 25 '17 at 09:10
  • 2
    @yugr one part of the question is "is the problem still there?" – Antti Haapala -- Слава Україні Apr 25 '17 at 09:11
  • @AnttiHaapala Right, +1'ed your comments. – yugr Apr 25 '17 at 09:20

1 Answers1

3

Basically this is a bug in GCC's -Wstrict-aliasing machinery. It's known to both produce false warnings and miss real aliasing violations (see this comment from developers).

The problem is there in both cases, casting unrelated structs will violate aliasing rules and will likely cause GCC to produce unexpected code.

yugr
  • 19,769
  • 3
  • 51
  • 96