From owner-freebsd-net@FreeBSD.ORG Thu Jun 6 20:23:31 2013 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mandree.no-ip.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by hub.freebsd.org (Postfix) with ESMTP id AC7C8E34 for ; Thu, 6 Jun 2013 20:23:31 +0000 (UTC) (envelope-from mandree@FreeBSD.org) Received: from [IPv6:::1] (localhost6.localdomain6 [IPv6:::1]) by apollo.emma.line.org (Postfix) with ESMTP id D8EA723CEB6 for ; Thu, 6 Jun 2013 22:23:30 +0200 (CEST) Message-ID: <51B0EFC2.1020406@FreeBSD.org> Date: Thu, 06 Jun 2013 22:23:30 +0200 From: Matthias Andree User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130510 Thunderbird/17.0.6 MIME-Version: 1.0 To: freebsd-net@freebsd.org Subject: IN6_IS_ADDR_* macros use invalid type punning? X-Enigmail-Version: 1.4.6 Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: 7bit X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 06 Jun 2013 20:23:32 -0000 -- NOTE -- Please Cc: me on replies, I am not subscribed to freebsd-net. Greetings, I am just staring at gcc 4.8 warnings when compiling the try.c code shown below: ---------------------------------------------------------------- $ cat try.c #include #include #include #include int f(void) { struct sockaddr_in6 sin6; int r = IN6_IS_ADDR_V4MAPPED((&sin6.sin6_addr)); return r; } ---------------------------------------------------------------- ---------------------------------------------------------------- $ gcc48 -Wall -O2 -c try.c try.c: In function 'f': try.c:9:5: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] int r = IN6_IS_ADDR_V4MAPPED((&sin6.sin6_addr)); ^ try.c:9:5: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] try.c:9:5: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] ---------------------------------------------------------------- This is on FreeBSD 9.1-RELEASE amd64. /usr/include/netinet6/in6.h contains: /* * Mapped */ #define IN6_IS_ADDR_V4MAPPED(a) \ ((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \ (*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \ (*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == ntohl(0x0000ffff))) So we indeed break C99/C11 aliasing rules here. Pedantically speaking, it would also have to be htonl() instead of ntohl() because the in6_addr is in network order, but it does not matter to the machine because either maps to __bswap32() anyway. The same in6.h also declares: struct in6_addr { union { uint8_t __u6_addr8[16]; uint16_t __u6_addr16[8]; uint32_t __u6_addr32[4]; } __u6_addr; /* 128-bit IP6 address */ }; Which would appear to open up an alias-safe way (sanctioned by the C standard, access through union containing the type) to reimplement the macro, which also makes the GCC 4.8 warning go away and is far more readable: /* * Mapped */ #define IN6_IS_ADDR_V4MAPPED(a) \ ((a)->__u6_addr.__u6_addr32[0] == 0 && \ (a)->__u6_addr.__u6_addr32[1] == 0 && \ (a)->__u6_addr.__u6_addr16[2] == htonl(0x0000ffff)) Similar considerations apply to the other IN6_IS_ADDR_* macros. Now, what do we do? Can we get these fixed in a reasonable timeframe? To whom, or where, would I submit a patch for all the macros so that it actually gets committed to HEAD and MFC'd to /9 and /8? Do we have unit tests for these macros? Should we add some? Best Matthias (I don't have src commit permission.) -- NOTE -- Please Cc: me on replies, I am not subscribed to freebsd-net.