bug-gnulib
[Top][All Lists]
Advanced

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

undefined behaviour findings


From: Bruno Haible
Subject: undefined behaviour findings
Date: Sat, 09 Mar 2019 20:33:38 +0100
User-agent: KMail/5.1.3 (Linux/4.4.0-141-generic; KDE/5.18.0; x86_64; ; )

Following Jeffrey Walton's example, I built and tested a gnulib
testdir with CC="gcc -fsanitize=undefined". Here are the findings.

Of course, since this is based on runtime tests, not gcc warnings, it does not
produce findings for modules without unit tests.

lib/bitrotate.h:98:14: runtime error: left shift of 43981 by 16 places cannot 
be represented in type 'int'
lib/bitrotate.h:109:25: runtime error: left shift of 43981 by 16 places cannot 
be represented in type 'int'

lib/bitset/table.c:784:54: runtime error: shift exponent 87 is too large for 
64-bit type 'long unsigned int'

lib/des.c:552:3: runtime error: left shift of 255 by 24 places cannot be 
represented in type 'int'
lib/des.c:437:3: runtime error: left shift of 242 by 24 places cannot be 
represented in type 'int'
lib/des.c:625:3: runtime error: left shift of 254 by 24 places cannot be 
represented in type 'int'

lib/xmemdup0.c:41:3: runtime error: null pointer passed as argument 2, which is 
declared to never be null

tests/test-c-stack.c:66:13: runtime error: load of null pointer of type 'char'

tests/test-canonicalize.c:74:15: runtime error: null pointer passed as argument 
1, which is declared to never be null

tests/test-count-leading-zeros.c:56:3: runtime error: left shift of 1804289383 
by 31 places cannot be represented in type 'int'
tests/test-count-leading-zeros.c:56:3: runtime error: left shift of negative 
value -2147483648

tests/test-count-one-bits.c:55:3: runtime error: left shift of 1804289383 by 31 
places cannot be represented in type 'int'
tests/test-count-one-bits.c:55:3: runtime error: left shift of negative value 
-2147483648

tests/test-count-trailing-zeros.c:56:3: runtime error: left shift of 1804289383 
by 31 places cannot be represented in type 'int'
tests/test-count-trailing-zeros.c:56:3: runtime error: left shift of negative 
value -2147483648

tests/test-memmem.c:84:26: runtime error: null pointer passed as argument 3, 
which is declared to never be null


Let me fix some of them here.


2019-03-09  Bruno Haible  <address@hidden>

        Fix undefined behaviour.
        * lib/bitrotate.h (rotl16, rotr16, rotl8, rotr8): Case x to
        'unsigned int', to avoid shift operations on 'int'.
        * lib/xmemdup0.c (xmemdup0): Don't invoke memcpy with a zero size.
        * tests/test-count-leading-zeros.c (main): Use a random number that has
        as many bits as TYPE, not only 2*15 or 2*31 bits.
        * tests/test-count-trailing-zeros.c (main): Likewise.
        * tests/test-count-one-bits.c (main): Likewise.
        * tests/test-memmem.c: Don't include "null-ptr.h".
        (main): Use zerosize_ptr() instead of null_ptr().
        * modules/memmem-tests (Files): Remove tests/null-ptr.h.

diff --git a/lib/bitrotate.h b/lib/bitrotate.h
index 862331e..04b9083 100644
--- a/lib/bitrotate.h
+++ b/lib/bitrotate.h
@@ -95,7 +95,8 @@ rotr_sz (size_t x, int n)
 BITROTATE_INLINE uint16_t
 rotl16 (uint16_t x, int n)
 {
-  return ((x << n) | (x >> (16 - n))) & UINT16_MAX;
+  return (((unsigned int) x << n) | ((unsigned int) x >> (16 - n)))
+         & UINT16_MAX;
 }
 
 /* Given an unsigned 16-bit argument X, return the value corresponding
@@ -106,7 +107,8 @@ rotl16 (uint16_t x, int n)
 BITROTATE_INLINE uint16_t
 rotr16 (uint16_t x, int n)
 {
-  return ((x >> n) | (x << (16 - n))) & UINT16_MAX;
+  return (((unsigned int) x >> n) | ((unsigned int) x << (16 - n)))
+         & UINT16_MAX;
 }
 
 /* Given an unsigned 8-bit argument X, return the value corresponding
@@ -117,7 +119,7 @@ rotr16 (uint16_t x, int n)
 BITROTATE_INLINE uint8_t
 rotl8 (uint8_t x, int n)
 {
-  return ((x << n) | (x >> (8 - n))) & UINT8_MAX;
+  return (((unsigned int) x << n) | ((unsigned int) x >> (8 - n))) & UINT8_MAX;
 }
 
 /* Given an unsigned 8-bit argument X, return the value corresponding
@@ -128,7 +130,7 @@ rotl8 (uint8_t x, int n)
 BITROTATE_INLINE uint8_t
 rotr8 (uint8_t x, int n)
 {
-  return ((x >> n) | (x << (8 - n))) & UINT8_MAX;
+  return (((unsigned int) x >> n) | ((unsigned int) x << (8 - n))) & UINT8_MAX;
 }
 
 _GL_INLINE_HEADER_END
diff --git a/lib/xmemdup0.c b/lib/xmemdup0.c
index 4f491be..57c1b59 100644
--- a/lib/xmemdup0.c
+++ b/lib/xmemdup0.c
@@ -38,7 +38,8 @@ char *
 xmemdup0 (void const *p, size_t s)
 {
   char *result = xcharalloc (s + 1);
-  memcpy (result, p, s);
+  if (s > 0)
+    memcpy (result, p, s);
   result[s] = 0;
   return result;
 }

diff --git a/tests/test-count-leading-zeros.c b/tests/test-count-leading-zeros.c
index 3caae7f..e94e37e 100644
--- a/tests/test-count-leading-zeros.c
+++ b/tests/test-count-leading-zeros.c
@@ -34,23 +34,34 @@ main (int argc, char *argv[])
 {
   int i, j;
 
-#define TEST_COUNT_LEADING_ZEROS(FUNC, TYPE, BITS, MAX, ONE)    \
-  ASSERT (FUNC (0) == BITS);                                    \
-  for (i = 0; i < BITS; i++)                                    \
-    {                                                           \
-      ASSERT (FUNC (ONE << i) == BITS - i - 1);                 \
-      for (j = 0; j < i; j++)                                   \
-        ASSERT (FUNC ((ONE << i) | (ONE << j)) == BITS - i - 1);\
-    }                                                           \
-  for (i = 0; i < 1000; i++)                                    \
-    {                                                           \
-      TYPE value = rand () ^ (rand () << 31 << 1);              \
-      int count = 0;                                            \
-      for (j = 0; j < BITS; j++)                                \
-        if (value & (ONE << j))                                 \
-          count = BITS - j - 1;                                 \
-      ASSERT (count == FUNC (value));                           \
-    }                                                           \
+#define TEST_COUNT_LEADING_ZEROS(FUNC, TYPE, BITS, MAX, ONE)     \
+  ASSERT (FUNC (0) == BITS);                                     \
+  for (i = 0; i < BITS; i++)                                     \
+    {                                                            \
+      ASSERT (FUNC (ONE << i) == BITS - i - 1);                  \
+      for (j = 0; j < i; j++)                                    \
+        ASSERT (FUNC ((ONE << i) | (ONE << j)) == BITS - i - 1); \
+    }                                                            \
+  for (i = 0; i < 1000; i++)                                     \
+    {                                                            \
+      /* RAND_MAX is most often 0x7fff or 0x7fffffff.  */        \
+      TYPE value =                                               \
+        (RAND_MAX <= 0xffff                                      \
+         ? ((TYPE) rand () >> 3)                                 \
+           ^ (((TYPE) rand () >> 3) << 12)                       \
+           ^ (((TYPE) rand () >> 3) << 24)                       \
+           ^ (((TYPE) rand () >> 3) << 30 << 6)                  \
+           ^ (((TYPE) rand () >> 3) << 30 << 18)                 \
+           ^ (((TYPE) rand () >> 3) << 30 << 30)                 \
+         : ((TYPE) rand () >> 3)                                 \
+           ^ (((TYPE) rand () >> 3) << 22)                       \
+           ^ (((TYPE) rand () >> 3) << 22 << 22));               \
+      int count = 0;                                             \
+      for (j = 0; j < BITS; j++)                                 \
+        if (value & (ONE << j))                                  \
+          count = BITS - j - 1;                                  \
+      ASSERT (count == FUNC (value));                            \
+    }                                                            \
   ASSERT (FUNC (MAX) == 0);
 
   TEST_COUNT_LEADING_ZEROS (count_leading_zeros, unsigned int,
diff --git a/tests/test-count-one-bits.c b/tests/test-count-one-bits.c
index 109f3ee..852e1d6 100644
--- a/tests/test-count-one-bits.c
+++ b/tests/test-count-one-bits.c
@@ -34,22 +34,33 @@ main (int argc, char *argv[])
 {
   int i, j;
 
-#define TEST_COUNT_ONE_BITS(FUNC, TYPE, BITS, MAX, ONE) \
-  ASSERT (FUNC (0) == 0);                               \
-  for (i = 0; i < BITS; i++)                            \
-    {                                                   \
-      ASSERT (FUNC (ONE << i) == 1);                    \
-      for (j = i + 1; j < BITS; j++)                    \
-        ASSERT (FUNC ((ONE << i) | (ONE << j)) == 2);   \
-    }                                                   \
-  for (i = 0; i < 1000; i++)                            \
-    {                                                   \
-      TYPE value = rand () ^ (rand () << 31 << 1);      \
-      int count = 0;                                    \
-      for (j = 0; j < BITS; j++)                        \
-        count += (value & (ONE << j)) != 0;             \
-      ASSERT (count == FUNC (value));                   \
-    }                                                   \
+#define TEST_COUNT_ONE_BITS(FUNC, TYPE, BITS, MAX, ONE)   \
+  ASSERT (FUNC (0) == 0);                                 \
+  for (i = 0; i < BITS; i++)                              \
+    {                                                     \
+      ASSERT (FUNC (ONE << i) == 1);                      \
+      for (j = i + 1; j < BITS; j++)                      \
+        ASSERT (FUNC ((ONE << i) | (ONE << j)) == 2);     \
+    }                                                     \
+  for (i = 0; i < 1000; i++)                              \
+    {                                                     \
+      /* RAND_MAX is most often 0x7fff or 0x7fffffff.  */ \
+      TYPE value =                                        \
+        (RAND_MAX <= 0xffff                               \
+         ? ((TYPE) rand () >> 3)                          \
+           ^ (((TYPE) rand () >> 3) << 12)                \
+           ^ (((TYPE) rand () >> 3) << 24)                \
+           ^ (((TYPE) rand () >> 3) << 30 << 6)           \
+           ^ (((TYPE) rand () >> 3) << 30 << 18)          \
+           ^ (((TYPE) rand () >> 3) << 30 << 30)          \
+         : ((TYPE) rand () >> 3)                          \
+           ^ (((TYPE) rand () >> 3) << 22)                \
+           ^ (((TYPE) rand () >> 3) << 22 << 22));        \
+      int count = 0;                                      \
+      for (j = 0; j < BITS; j++)                          \
+        count += (value & (ONE << j)) != 0;               \
+      ASSERT (count == FUNC (value));                     \
+    }                                                     \
   ASSERT (FUNC (MAX) == BITS);
 
   TEST_COUNT_ONE_BITS (count_one_bits, unsigned int, UINT_BIT, UINT_MAX, 1U);
diff --git a/tests/test-count-trailing-zeros.c 
b/tests/test-count-trailing-zeros.c
index 5a18599..04d9ddc 100644
--- a/tests/test-count-trailing-zeros.c
+++ b/tests/test-count-trailing-zeros.c
@@ -34,23 +34,34 @@ main (int argc, char *argv[])
 {
   int i, j;
 
-#define TEST_COUNT_TRAILING_ZEROS(FUNC, TYPE, BITS, MAX, ONE)   \
-  ASSERT (FUNC (0) == BITS);                                    \
-  for (i = 0; i < BITS; i++)                                    \
-    {                                                           \
-      ASSERT (FUNC (ONE << i) == i);                            \
-      for (j = 0; j < i; j++)                                   \
-        ASSERT (FUNC ((ONE << i) | (ONE << j)) == j);           \
-    }                                                           \
-  for (i = 0; i < 1000; i++)                                    \
-    {                                                           \
-      TYPE value = rand () ^ (rand () << 31 << 1);              \
-      int count = 0;                                            \
-      for (j = BITS - 1; 0 <= j; j--)                           \
-        if (value & (ONE << j))                                 \
-          count = j;                                            \
-      ASSERT (count == FUNC (value));                           \
-    }                                                           \
+#define TEST_COUNT_TRAILING_ZEROS(FUNC, TYPE, BITS, MAX, ONE) \
+  ASSERT (FUNC (0) == BITS);                                  \
+  for (i = 0; i < BITS; i++)                                  \
+    {                                                         \
+      ASSERT (FUNC (ONE << i) == i);                          \
+      for (j = 0; j < i; j++)                                 \
+        ASSERT (FUNC ((ONE << i) | (ONE << j)) == j);         \
+    }                                                         \
+  for (i = 0; i < 1000; i++)                                  \
+    {                                                         \
+      /* RAND_MAX is most often 0x7fff or 0x7fffffff.  */     \
+      TYPE value =                                            \
+        (RAND_MAX <= 0xffff                                   \
+         ? ((TYPE) rand () >> 3)                              \
+           ^ (((TYPE) rand () >> 3) << 12)                    \
+           ^ (((TYPE) rand () >> 3) << 24)                    \
+           ^ (((TYPE) rand () >> 3) << 30 << 6)               \
+           ^ (((TYPE) rand () >> 3) << 30 << 18)              \
+           ^ (((TYPE) rand () >> 3) << 30 << 30)              \
+         : ((TYPE) rand () >> 3)                              \
+           ^ (((TYPE) rand () >> 3) << 22)                    \
+           ^ (((TYPE) rand () >> 3) << 22 << 22));            \
+      int count = 0;                                          \
+      for (j = BITS - 1; 0 <= j; j--)                         \
+        if (value & (ONE << j))                               \
+          count = j;                                          \
+      ASSERT (count == FUNC (value));                         \
+    }                                                         \
   ASSERT (FUNC (MAX) == 0);
 
   TEST_COUNT_TRAILING_ZEROS (count_trailing_zeros, unsigned int,
diff --git a/tests/test-memmem.c b/tests/test-memmem.c
index ed327e6..17e2e41 100644
--- a/tests/test-memmem.c
+++ b/tests/test-memmem.c
@@ -26,7 +26,6 @@ SIGNATURE_CHECK (memmem, void *, (void const *, size_t, void 
const *, size_t));
 #include <stdlib.h>
 #include <unistd.h>
 
-#include "null-ptr.h"
 #include "zerosize-ptr.h"
 #include "macros.h"
 
@@ -81,7 +80,7 @@ main (int argc, char *argv[])
 
   {
     const char input[] = "foo";
-    const char *result = memmem (input, strlen (input), null_ptr (), 0);
+    const char *result = memmem (input, strlen (input), zerosize_ptr (), 0);
     ASSERT (result == input);
   }
 
diff --git a/modules/memmem-tests b/modules/memmem-tests
index 28c0091..250ccbf 100644
--- a/modules/memmem-tests
+++ b/modules/memmem-tests
@@ -1,7 +1,6 @@
 Files:
 tests/test-memmem.c
 tests/signature.h
-tests/null-ptr.h
 tests/zerosize-ptr.h
 tests/macros.h
 m4/mmap-anon.m4



reply via email to

[Prev in Thread] Current Thread [Next in Thread]