[PATCH] Silence -Wshift-count-overflow warnings

Jan Dubiec <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
This patch fixes a few "left shift count >= width of type
[-Wshift-count-overflow]" warnings. Before shifting a char 16 (or more)
bits left first it explicitly casts the char to uint32_t. The existing
code relies on implicit casts to int and assumes that ints are 32-bit.
This is not always true because the C standard does not require int to
be 32-bit and there are targets (e.g. H8/300) where by default int is
indeed 16-bit.

2025-03-02  Jan Dubiec  <[email protected]>

newlib/ChangeLog:

	* libc/stdlib/gdtoa-gdtoa.c (gdtoa): Cast to __ULong before left shift.
	* libc/string/memmem.c (memmem): Cast to uint32_t before left shift.
	* libc/string/strstr.c (strstr2): Ditto.
	(strstr3): Ditto.
	(strstr4): Ditto.
shift-count-overflow.patch (text/plain, 2.5 KB)
 newlib/libc/stdlib/gdtoa-gdtoa.c | 2 +-
 newlib/libc/string/memmem.c      | 3 ++-
 newlib/libc/string/strstr.c      | 6 +++---
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/newlib/libc/stdlib/gdtoa-gdtoa.c b/newlib/libc/stdlib/gdtoa-gdtoa.c
index da2338c48..d29a81eab 100644
--- a/newlib/libc/stdlib/gdtoa-gdtoa.c
+++ b/newlib/libc/stdlib/gdtoa-gdtoa.c
@@ -261,7 +261,7 @@ gdtoa
 		dval(d) *= 1 << j1;
 	word0(d) += j << Exp_shift - 2 & Exp_mask;
 #else
-	word0(d) += (be + bbits - 1) << Exp_shift;
+	word0(d) += (__ULong)(be + bbits - 1) << Exp_shift;
 #endif
 	if (k >= 0 && k <= Ten_pmax) {
 		if (dval(d) < tens[k])
diff --git a/newlib/libc/string/memmem.c b/newlib/libc/string/memmem.c
index 65267b9c5..13d8c0a9f 100644
--- a/newlib/libc/string/memmem.c
+++ b/newlib/libc/string/memmem.c
@@ -129,7 +129,8 @@ memmem (const void *haystack, size_t hs_len, const void *needle, size_t ne_len)
 
   if (ne_len == 2)
     {
-      uint32_t nw = ne[0] << 16 | ne[1], hw = hs[0] << 16 | hs[1];
+      uint32_t nw = ((uint32_t)ne[0] << 16) | ne[1],
+			   hw = ((uint32_t)hs[0] << 16) | hs[1];
       for (hs++; hs <= end && hw != nw; )
 	hw = hw << 16 | *++hs;
       return hw == nw ? (void *)(hs - 1) : NULL;
diff --git a/newlib/libc/string/strstr.c b/newlib/libc/string/strstr.c
index 84e4632f1..50dbbec05 100644
--- a/newlib/libc/string/strstr.c
+++ b/newlib/libc/string/strstr.c
@@ -100,7 +100,7 @@ strstr (const char *hs, const char *ne)
 static inline char *
 strstr2 (const unsigned char *hs, const unsigned char *ne)
 {
-  uint32_t h1 = (ne[0] << 16) | ne[1];
+  uint32_t h1 = ((uint32_t)ne[0] << 16) | ne[1];
   uint32_t h2 = 0;
   int c;
   for (c = hs[0]; h1 != h2 && c != 0; c = *++hs)
@@ -111,7 +111,7 @@ strstr2 (const unsigned char *hs, const unsigned char *ne)
 static inline char *
 strstr3 (const unsigned char *hs, const unsigned char *ne)
 {
-  uint32_t h1 = (ne[0] << 24) | (ne[1] << 16) | (ne[2] << 8);
+  uint32_t h1 = ((uint32_t)ne[0] << 24) | ((uint32_t)ne[1] << 16) | (ne[2] << 8);
   uint32_t h2 = 0;
   int c;
   for (c = hs[0]; h1 != h2 && c != 0; c = *++hs)
@@ -122,7 +122,7 @@ strstr3 (const unsigned char *hs, const unsigned char *ne)
 static inline char *
 strstr4 (const unsigned char *hs, const unsigned char *ne)
 {
-  uint32_t h1 = (ne[0] << 24) | (ne[1] << 16) | (ne[2] << 8) | ne[3];
+  uint32_t h1 = ((uint32_t)ne[0] << 24) | ((uint32_t)ne[1] << 16) | (ne[2] << 8) | ne[3];
   uint32_t h2 = 0;
   int c;
   for (c = hs[0]; c != 0 && h1 != h2; c = *++hs)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.