From 1afce9573a3c1fed4d2b758259cb0eddde89729a Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 22 Jun 2016 14:22:11 +0200 Subject: [PATCH] lib: endianness: don't break strict-aliasing Strict aliasing prohibits writing to union members of one type, then reading another type. The read is undefined. Use memcpy instead (which compilers will hopefully optimize away...) --- lib/capnp_c.h | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/lib/capnp_c.h b/lib/capnp_c.h index f1baa7a..d2f905d 100644 --- a/lib/capnp_c.h +++ b/lib/capnp_c.h @@ -13,6 +13,7 @@ #include #include +#include #if defined(unix) && !defined(__APPLE__) #include #endif @@ -316,10 +317,12 @@ CAPN_INLINE uint16_t capn_flip16(uint16_t v) { defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 return __builtin_bswap16(v); #else - union { uint16_t u; uint8_t v[2]; } s; - s.v[0] = (uint8_t)v; - s.v[1] = (uint8_t)(v>>8); - return s.u; + uint8_t sv[2]; + uint16_t ret; + sv[0] = (uint8_t)v; + sv[1] = (uint8_t)(v>>8); + memcpy(&ret, sv, sizeof(ret)); + return ret; #endif } CAPN_INLINE uint32_t capn_flip32(uint32_t v) { @@ -329,12 +332,14 @@ CAPN_INLINE uint32_t capn_flip32(uint32_t v) { defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 return __builtin_bswap32(v); #else - union { uint32_t u; uint8_t v[4]; } s; - s.v[0] = (uint8_t)v; - s.v[1] = (uint8_t)(v>>8); - s.v[2] = (uint8_t)(v>>16); - s.v[3] = (uint8_t)(v>>24); - return s.u; + uint8_t sv[4]; + uint32_t ret; + sv[0] = (uint8_t)v; + sv[1] = (uint8_t)(v>>8); + sv[2] = (uint8_t)(v>>16); + sv[3] = (uint8_t)(v>>24); + memcpy(&ret, sv, sizeof(ret)); + return ret; #endif } CAPN_INLINE uint64_t capn_flip64(uint64_t v) { @@ -344,16 +349,18 @@ CAPN_INLINE uint64_t capn_flip64(uint64_t v) { defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 return __builtin_bswap64(v); #else - union { uint64_t u; uint8_t v[8]; } s; - s.v[0] = (uint8_t)v; - s.v[1] = (uint8_t)(v>>8); - s.v[2] = (uint8_t)(v>>16); - s.v[3] = (uint8_t)(v>>24); - s.v[4] = (uint8_t)(v>>32); - s.v[5] = (uint8_t)(v>>40); - s.v[6] = (uint8_t)(v>>48); - s.v[7] = (uint8_t)(v>>56); - return s.u; + uint8_t sv[8]; + uint64_t ret; + sv[0] = (uint8_t)v; + sv[1] = (uint8_t)(v>>8); + sv[2] = (uint8_t)(v>>16); + sv[3] = (uint8_t)(v>>24); + sv[4] = (uint8_t)(v>>32); + sv[5] = (uint8_t)(v>>40); + sv[6] = (uint8_t)(v>>48); + sv[7] = (uint8_t)(v>>56); + memcpy(&ret, sv, sizeof(ret)); + return ret; #endif }