From 5ecf765c088190267137cdc7223ce3d835d224b5 Mon Sep 17 00:00:00 2001 From: Jarno Rajahalme Date: Thu, 27 Aug 2015 10:48:03 -0700 Subject: [PATCH] flow: Workaround for GCC false-positive compilation error. Without an explicit bounds check GCC 4.9 issues an array out of bounds error. This patch adds explicit checks which will however be optimized away as the relevant parameters are compile-time constants. Signed-off-by: Jarno Rajahalme Acked-by: Ben Pfaff --- lib/flow.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/flow.h b/lib/flow.h index 323cbdbb5..25172e0ed 100644 --- a/lib/flow.h +++ b/lib/flow.h @@ -478,7 +478,9 @@ flowmap_are_set(const struct flowmap *fm, size_t idx, unsigned int n_bits) if (fm->bits[unit] & (n_bits_mask << idx)) { return true; } - if (idx + n_bits > MAP_T_BITS) { + /* The seemingly unnecessary bounds check on 'unit' is a workaround for a + * false-positive array out of bounds error by GCC 4.9. */ + if (unit + 1 < FLOWMAP_UNITS && idx + n_bits > MAP_T_BITS) { /* Check the remaining bits from the next unit. */ return fm->bits[unit + 1] & (n_bits_mask >> (MAP_T_BITS - idx)); } @@ -496,7 +498,9 @@ flowmap_set(struct flowmap *fm, size_t idx, unsigned int n_bits) idx %= MAP_T_BITS; fm->bits[unit] |= n_bits_mask << idx; - if (idx + n_bits > MAP_T_BITS) { + /* The seemingly unnecessary bounds check on 'unit' is a workaround for a + * false-positive array out of bounds error by GCC 4.9. */ + if (unit + 1 < FLOWMAP_UNITS && idx + n_bits > MAP_T_BITS) { /* 'MAP_T_BITS - idx' bits were set on 'unit', set the remaining * bits from the next unit. */ fm->bits[unit + 1] |= n_bits_mask >> (MAP_T_BITS - idx); @@ -514,7 +518,9 @@ flowmap_clear(struct flowmap *fm, size_t idx, unsigned int n_bits) idx %= MAP_T_BITS; fm->bits[unit] &= ~(n_bits_mask << idx); - if (idx + n_bits > MAP_T_BITS) { + /* The seemingly unnecessary bounds check on 'unit' is a workaround for a + * false-positive array out of bounds error by GCC 4.9. */ + if (unit + 1 < FLOWMAP_UNITS && idx + n_bits > MAP_T_BITS) { /* 'MAP_T_BITS - idx' bits were cleared on 'unit', clear the * remaining bits from the next unit. */ fm->bits[unit + 1] &= ~(n_bits_mask >> (MAP_T_BITS - idx)); -- 2.20.1