[ovs-dev] [PATCH] byte-order: Fix undefined behavior of BYTES_TO_BE32.
Ben Pfaff
blp at ovn.org
Tue Jun 13 04:51:14 UTC 2017
A left shift that would produce a result that is not representable
by the type of the expression's result has "undefined behavior"
according to the C language standard. Avoid this by casting values
that could set the upper bit to unsigned types.
Also document and convert a macro to a function.
While we're at it, delete the unused macro BE16S_TO_BE32.
Found via gcc's undefined behavior sanitizer.
Reported-by: Lance Richardson <lrichard at redhat.com>
Signed-off-by: Ben Pfaff <blp at ovn.org>
---
lib/byte-order.h | 21 +++++++++++++--------
lib/flow.c | 2 +-
2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/lib/byte-order.h b/lib/byte-order.h
index e864658f9b59..b2a9082bbada 100644
--- a/lib/byte-order.h
+++ b/lib/byte-order.h
@@ -98,17 +98,22 @@ uint32_byteswap(uint32_t crc) {
((((ovs_be64) (VALUE)) & UINT64_C(0xff00000000000000)) >> 56))
#endif
+/* Returns the ovs_be32 that you would get from:
+ *
+ * union { uint8_t b[4]; ovs_be32 be32; } x = { .b = { b0, b1, b2, b3 } };
+ * return x.be32;
+ *
+ * but without the undefined behavior. */
+static inline ovs_be32
+bytes_to_be32(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3)
+{
#if WORDS_BIGENDIAN
-#define BYTES_TO_BE32(B1, B2, B3, B4) \
- (OVS_FORCE ovs_be32)((uint32_t)(B1) << 24 | (B2) << 16 | (B3) << 8 | (B4))
-#define BE16S_TO_BE32(B1, B2) \
- (OVS_FORCE ovs_be32)((uint32_t)(B1) << 16 | (B2))
+ uint32_t x = ((uint32_t) b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
#else
-#define BYTES_TO_BE32(B1, B2, B3, B4) \
- (OVS_FORCE ovs_be32)((uint32_t)(B1) | (B2) << 8 | (B3) << 16 | (B4) << 24)
-#define BE16S_TO_BE32(B1, B2) \
- (OVS_FORCE ovs_be32)((uint32_t)(B1) | (B2) << 16)
+ uint32_t x = ((uint32_t) b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
#endif
+ return (OVS_FORCE ovs_be32) x;
+}
/* These functions zero-extend big-endian values to longer ones,
* or truncate long big-endian value to shorter ones. */
diff --git a/lib/flow.c b/lib/flow.c
index 1f51b66e7b44..d73e796a2f45 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -823,7 +823,7 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
packet->l4_ofs = (char *)data - frame;
miniflow_push_be32(mf, nw_frag,
- BYTES_TO_BE32(nw_frag, nw_tos, nw_ttl, nw_proto));
+ bytes_to_be32(nw_frag, nw_tos, nw_ttl, nw_proto));
if (OVS_LIKELY(!(nw_frag & FLOW_NW_FRAG_LATER))) {
if (OVS_LIKELY(nw_proto == IPPROTO_TCP)) {
--
2.10.2
More information about the dev
mailing list