macros: avoid signed overflow in nm_utils_is_power_of_two()

If __x is signed and its value is the minimum allowed for the type,
(__x - 1) causes a signed overflow, which has an undefined
behavior. Compiling with -fsanitize=undefined produces the warnings:

test-general.c:4499:619: runtime error: signed integer overflow: -2147483648 - 1 cannot be represented in type 'int'
test-general.c:4506:681: runtime error: signed integer overflow: -2147483648 - 1 cannot be represented in type 'TEST_IS_POWER_OF_TWP_ENUM_SIGNED'
test-general.c:4501:619: runtime error: signed integer overflow: -9223372036854775808 - 1 cannot be represented in type 'long int'
test-general.c:4509:691: runtime error: signed integer overflow: -9223372036854775808 - 1 cannot be represented in type 'TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED_64'

Change the order of expressions to avoid this.

Fixes: 0a3c1f5774
(cherry picked from commit bc9d034775)
This commit is contained in:
Beniamino Galvani 2015-11-15 11:13:29 +01:00
parent bd5a4c6f6a
commit 18770ece53

View file

@ -277,12 +277,12 @@ nm_clear_g_signal_handler (gpointer self, guint *id)
#define nm_utils_is_power_of_two(x) ({ \
const typeof(x) __x = (x); \
\
((__x & (__x - 1)) == 0) && \
/* Check if the value is negative. In that case, return FALSE.
* The first expression is a compile time constant, depending on whether
* the type is signed. The second expression is a clumsy way for (__x >= 0),
* which causes a compiler warning for unsigned types. */ \
( ( ((typeof(__x)) -1) > ((typeof(__x)) 0) ) || (__x > 0) || (__x == 0) ); \
/* Check if the value is negative. In that case, return FALSE.
* The first expression is a compile time constant, depending on whether
* the type is signed. The second expression is a clumsy way for (__x >= 0),
* which causes a compiler warning for unsigned types. */ \
( ( ((typeof(__x)) -1) > ((typeof(__x)) 0) ) || (__x > 0) || (__x == 0) ) \
&& ((__x & (__x - 1)) == 0); \
})
/*****************************************************************************/