This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Make endian-conversion macros always return correct types (bug 16458)
- From: Siddhesh Poyarekar <siddhesh at gotplt dot org>
- To: libc-alpha at sourceware dot org
- Date: Wed, 11 Jan 2017 19:58:10 +0530
- Subject: Re: Make endian-conversion macros always return correct types (bug 16458)
- Authentication-results: sourceware.org; auth=none
- References: <alpine.DEB.2.20.1701100340230.8116@digraph.polyomino.org.uk>
On Tuesday 10 January 2017 09:13 AM, Joseph Myers wrote:
> Bug 16458 reports that the endian-conversion macros in <endian.h> and
> <netinet/in.h>, in the case where no endian conversion is needed, just
> return their arguments without converting to the expected return type,
> so failing to act as expected for a macro version of a function. (The
> <netinet/in.h> macros, in particular, are described with prototypes in
> POSIX so should act like correspondingly prototyped functions.)
>
> Where previously this was a fairly obscure issue, it now results in
> glibc build with GCC mainline breaking for big-endian systems:
>
> nss_hesiod/hesiod-service.c: In function '_nss_hesiod_getservbyport_r':
> nss_hesiod/hesiod-service.c:142:39: error: '%d' directive output may be truncated writing between 1 and 11 bytes into a region of size 6 [-Werror=format-truncation=]
> snprintf (portstr, sizeof portstr, "%d", ntohs (port));
> ^~
> nss_hesiod/hesiod-service.c:142:38: note: using the range [1, -2147483648] for directive argument
> snprintf (portstr, sizeof portstr, "%d", ntohs (port));
> ^~~~
> nss_hesiod/hesiod-service.c:142:3: note: format output between 2 and 12 bytes into a destination of size 6
> snprintf (portstr, sizeof portstr, "%d", ntohs (port));
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> The port argument is passed as int to this function, so when ntohs
> does not convert the compiler cannot tell that the result is within
> the range of uint16_t. (I don't know if in fact it's possible for
> out-of-range values to reach this function and so get truncated as
> strings without this patch or as integers with it.)
>
> This patch arranges for these macros to use identity functions to
> ensure appropriate conversions while having warnings for implicit
> conversions of function arguments that might not occur with a cast.
>
> Tested for x86_64 and x86; with build-many-glibcs.py with GCC 6; and
> with build-many-glibcs.py with GCC mainline for powerpc to test the
> build fix.
>
> 2017-01-10 Joseph Myers <joseph@codesourcery.com>
>
> [BZ #16458]
> * bits/uintn-identity.h: New file.
> * inet/netinet/in.h: Include <bits/uintn-identity.h>.
> [__BYTE_ORDER == __BIG_ENDIAN] (ntohl): Use __uint32_identity.
> [__BYTE_ORDER == __BIG_ENDIAN] (ntohs): Use __uint16_identity.
> [__BYTE_ORDER == __BIG_ENDIAN] (htonl): Use __uint32_identity.
> [__BYTE_ORDER == __BIG_ENDIAN] (htohs): Use __uint16_identity.
> * string/endian.h: Include <bits/uintn-identity.h>.
> [__BYTE_ORDER == __LITTLE_ENDIAN] (htole16): Use
> __uint16_identity.
> [__BYTE_ORDER == __LITTLE_ENDIAN] (le16toh): Likewise.
> [__BYTE_ORDER == __LITTLE_ENDIAN] (htole32): Use
> __uint32_identity.
> [__BYTE_ORDER == __LITTLE_ENDIAN] (le32toh): Likewise.
> [__BYTE_ORDER == __LITTLE_ENDIAN] (htole64): Use
> __uint64_identity.
> [__BYTE_ORDER == __LITTLE_ENDIAN] (le64toh): Likewise.
> [__BYTE_ORDER != __LITTLE_ENDIAN] (htobe16): Use
> __uint16_identity.
> [__BYTE_ORDER != __LITTLE_ENDIAN] (be16toh): Likewise.
> [__BYTE_ORDER != __LITTLE_ENDIAN] (htobe32): Use
> __uint32_identity.
> [__BYTE_ORDER != __LITTLE_ENDIAN] (be32toh): Likewise.
> [__BYTE_ORDER != __LITTLE_ENDIAN] (htobe64): Use
> __uint64_identity.
> [__BYTE_ORDER != __LITTLE_ENDIAN] (be64toh): Likewise.
> * string/Makefile (headers): Add bits/uintn-identity.h.
> (tests): Add test-endian-types.
> * string/test-endian-types.c: New file.
> * inet/Makefile (tests): Add test-hnto-types.
> * inet/test-hnto-types.c: New file.
Looks OK to me.
Siddhesh