From patchwork Sat Jul 30 22:59:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aurelien Jarno X-Patchwork-Id: 14165 Received: (qmail 24762 invoked by alias); 30 Jul 2016 22:59:52 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 24746 invoked by uid 89); 30 Jul 2016 22:59:51 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.3 required=5.0 tests=BAYES_20, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=20160731, 2016-07-31, hongjiuluintelcom, hongjiu.lu@intel.com X-HELO: hall.aurel32.net From: Aurelien Jarno To: libc-alpha@sourceware.org Cc: Aurelien Jarno Subject: [PATCH] Fix htonl, htons, ntohl, ntohs functions on big endian systems Date: Sun, 31 Jul 2016 00:59:29 +0200 Message-Id: <1469919569-27798-1-git-send-email-aurelien@aurel32.net> The htonl, htons, ntohl and ntohs funtions are defined by POSIX as: uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort); They take a uint16_t or uint32_t argument and return a value with the same type. This means for example that calling htonl on a 64-bit value should return a 32-bit value. The GNU libc implements these functions as macros when optimizations are enabled, and this is explicitely allowed by POSIX. However on big endian systems there are then defined as: # define ntohl(x) (x) # define ntohs(x) (x) # define htonl(x) (x) # define htons(x) (x) This means that the values are not casted if the argument is bigger. In turns that means that: - the behaviour is different between little and big endian systems; - the behaviour depends on the optimization level. This patch attempts to fix that. It adds an implicit cast for ntohl and htonl using a GCC extension or an explicit one when not using GCC. It adds an explicit cast for ntohs and htons as the call to __bswap_16 contains an explicit cast. Changelog: * inet/netinet/in.h [__OPTIMIZE__ && (__BYTE_ORDER == __BIG_ENDIAN)] (ntohl): Add an implicit uint32_t cast if [__GNUC__ >= 2] or an explicit uint32_t cast if [!__GNUC__ >= 2]. [__OPTIMIZE__ && (__BYTE_ORDER == __BIG_ENDIAN)] (htonl): Likewise. [__OPTIMIZE__ && (__BYTE_ORDER == __BIG_ENDIAN)] (ntohs): Add a uint16_t cast. [__OPTIMIZE__ && (__BYTE_ORDER == __BIG_ENDIAN)] (htons): Likewise. --- ChangeLog | 10 ++++++++++ inet/netinet/in.h | 19 +++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) Note: the macros in also suffer from the same issue. I'll send a patch for them if this change is considered acceptable. diff --git a/ChangeLog b/ChangeLog index f148ac8..ee1b091 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2016-07-31 Aurelien Jarno + + * inet/netinet/in.h [__OPTIMIZE__ && (__BYTE_ORDER == __BIG_ENDIAN)] + (ntohl): Add an implicit uint32_t cast if [__GNUC__ >= 2] or an + explicit uint32_t cast if [!__GNUC__ >= 2]. + [__OPTIMIZE__ && (__BYTE_ORDER == __BIG_ENDIAN)] (htonl): Likewise. + [__OPTIMIZE__ && (__BYTE_ORDER == __BIG_ENDIAN)] (ntohs): Add a uint16_t + cast. + [__OPTIMIZE__ && (__BYTE_ORDER == __BIG_ENDIAN)] (htons): Likewise. + 2016-07-27 H.J. Lu [BZ #20384] diff --git a/inet/netinet/in.h b/inet/netinet/in.h index c801593..86e812a 100644 --- a/inet/netinet/in.h +++ b/inet/netinet/in.h @@ -393,10 +393,21 @@ extern uint16_t htons (uint16_t __hostshort) # if __BYTE_ORDER == __BIG_ENDIAN /* The host byte order is the same as network byte order, so these functions are all just identity. */ -# define ntohl(x) (x) -# define ntohs(x) (x) -# define htonl(x) (x) -# define htons(x) (x) +# if defined __GNUC__ && __GNUC__ >= 2 +# define ntohl(x) \ + (__extension__ \ + ({ uint32_t __x = x; \ + __x; })) +# define htonl(x) \ + (__extension__ \ + ({ uint32_t __x = x; \ + __x; })) +# else +# define ntohl(x) ((uint32_t) (x)) +# define htonl(x) ((uint32_t) (x)) +# endif +# define ntohs(x) ((uint16_t) (x)) +# define htons(x) ((uint16_t) (x)) # else # if __BYTE_ORDER == __LITTLE_ENDIAN # define ntohl(x) __bswap_32 (x)