[PATCH BlueZ 2/2] shared: Fix undefined behavior when calculating next power of two

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



According to GCC documentation, __builtin_clz() is undefined if argument
is zero. The following problem was detected when compiling with -O0:

ERROR:unit/test-ringbuf.c:70:test_power2: assertion failed: (size1 ==
size2)

Also refactor align_power2() so the internal "find last set bit"
operation is in its own fls() function (similar to how kernel does).
fls() checks if argument is zero before calling __builtin_clz().
---
 src/shared/ringbuf.c | 9 ++++++++-
 unit/test-ringbuf.c  | 7 ++++++-
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/shared/ringbuf.c b/src/shared/ringbuf.c
index 3e5c7d3..f9c4376 100644
--- a/src/shared/ringbuf.c
+++ b/src/shared/ringbuf.c
@@ -48,9 +48,16 @@ struct ringbuf {
 
 #define RINGBUF_RESET 0
 
+/* Find last (most siginificant) set bit */
+static inline unsigned int fls(unsigned int x)
+{
+	return x ? sizeof(x) * 8 - __builtin_clz(x) : 0;
+}
+
+/* Round up to nearest power of two */
 static inline unsigned int align_power2(unsigned int u)
 {
-	return 1 << ((sizeof(u) * 8) - __builtin_clz(u - 1));
+	return 1 << fls(u - 1);
 }
 
 struct ringbuf *ringbuf_new(size_t size)
diff --git a/unit/test-ringbuf.c b/unit/test-ringbuf.c
index e63321c..75be3a3 100644
--- a/unit/test-ringbuf.c
+++ b/unit/test-ringbuf.c
@@ -45,9 +45,14 @@ static unsigned int nlpo2(unsigned int x)
 	return x + 1;
 }
 
+static unsigned int fls(unsigned int x)
+{
+	return x ? sizeof(x) * 8 - __builtin_clz(x) : 0;
+}
+
 static unsigned int align_power2(unsigned int u)
 {
-	return 1 << ((sizeof(u) * 8) - __builtin_clz(u - 1));
+	return 1 << fls(u - 1);
 }
 
 static void test_power2(void)
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux