Search code examples
cstrict-aliasing

Am I violating strict aliasing rules by creating dummy struct data types?


I have these two functions:

static inline void *ether_payload(void *pkt)
{
  return ((char*)pkt) + 14;
}
static inline uint16_t ip_id(const void *pkt)
{
  const char *cpkt = pkt;
  uint16_t id;
  memcpy(&id, &cpkt[4], sizeof(id));
  return ntohs(id);
}

Now, there's a type safety issue. For the first function, void pointer means Ethernet header. For the second function, void pointer means IPv4 header. This creates a huge possibility that somebody accidentally calls the second function for an Ethernet header directly. If somebody does so, the compiler gives no warning.

I would like to eliminate this type safety issue through two dummy structs the contents of which are never defined:

struct etherhdr;
struct ipv4hdr;

Now the functions would be:

static inline struct ipv4hdr *ether_payload(struct etherhdr *pkt)
{
  return (struct ipv4hdr*)(((char*)pkt) + 14);
}
static inline uint16_t ip_id(const struct ipv4hdr *pkt)
{
  const char *cpkt = (const char*)pkt;
  uint16_t id;
  memcpy(&id, &cpkt[4], sizeof(id));
  return ntohs(id);
}

This solves the type safety issue. Note I'm not actually accessing the Ethernet or IP headers through a struct which would be very bad practice indeed.

My question is, am I violating strict aliasing rules by defining such an API? Note the data is never accessed via the struct; the data is just accessed via memcpy using a char pointer. My understanding is that char pointer can alias to anything.

Let's leave the fact that Ethernet packet can contain IPv6 as irrelevant, as this was just a very simple example.


Solution

  • As for answering your question, it was already answered by Cornstalks, no, you are not violating any strict aliasing rules.
    You may convert a pointer to a char pointer. You may convert char pointer to another pointer if you are sure, that this another pointer is really there. See Strict aliasing rule and 'char *' pointers