[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
- undefined behaviour findings,
Bruno Haible <=
- Re: undefined behaviour findings in bitset, Bruno Haible, 2019/03/09
- Re: undefined behaviour findings in bitset, Akim Demaille, 2019/03/16
- Re: undefined behaviour findings in bitset, Akim Demaille, 2019/03/16
- Re: undefined behaviour findings in bitset, Bruno Haible, 2019/03/16
- Re: undefined behaviour findings in bitset, Akim Demaille, 2019/03/17
- Re: undefined behaviour findings in bitset, Akim Demaille, 2019/03/17
- Re: undefined behaviour findings in bitset, Paul Eggert, 2019/03/17
- Re: undefined behaviour findings in bitset, Bruno Haible, 2019/03/17
- Re: undefined behaviour findings in bitset, Akim Demaille, 2019/03/18
- Re: undefined behaviour findings in bitset, Bruno Haible, 2019/03/18