This patch from pgerell at GitHub adds some casts to libbacktrace to
avoid undefined shifts. These shifts are OK on all real systems but
may as well get it right. Bootstrapped and ran libbacktrace tests on
x86_64-pc-linux-gnu. Committed to mainline.

Ian

libbacktrace: add casts to avoid undefined shifts

Patch from pgerell@github.

* elf.c (elf_fetch_bits): Add casts to avoid potentially shifting
a value farther than its type size.
(elf_fetch_bits_backward): Likewise.
(elf_uncompress_lzma_block): Likewise.
(elf_uncompress_lzma): Likewise.
db23cdf5d7b714d1ca7fe649cdd2a8aced383aac
diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c
index a450f3535c6..d766fa41a61 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -1147,7 +1147,10 @@ elf_fetch_bits (const unsigned char **ppin, const 
unsigned char *pinend,
   next = __builtin_bswap32 (next);
 #endif
 #else
-  next = pin[0] | (pin[1] << 8) | (pin[2] << 16) | (pin[3] << 24);
+  next = ((uint32_t)pin[0]
+         | ((uint32_t)pin[1] << 8)
+         | ((uint32_t)pin[2] << 16)
+         | ((uint32_t)pin[3] << 24));
 #endif
 
   val |= (uint64_t)next << bits;
@@ -1198,7 +1201,10 @@ elf_fetch_bits_backward (const unsigned char **ppin,
   next = __builtin_bswap32 (next);
 #endif
 #else
-  next = pin[0] | (pin[1] << 8) | (pin[2] << 16) | (pin[3] << 24);
+  next = ((uint32_t)pin[0]
+         | ((uint32_t)pin[1] << 8)
+         | ((uint32_t)pin[2] << 16)
+         | ((uint32_t)pin[3] << 24));
 #endif
 
   val <<= 32;
@@ -5872,10 +5878,10 @@ elf_uncompress_lzma_block (const unsigned char 
*compressed,
          /* The byte at compressed[off] is ignored for some
             reason.  */
 
-         code = ((compressed[off + 1] << 24)
-                 + (compressed[off + 2] << 16)
-                 + (compressed[off + 3] << 8)
-                 + compressed[off + 4]);
+         code = ((uint32_t)(compressed[off + 1] << 24)
+                 + ((uint32_t)compressed[off + 2] << 16)
+                 + ((uint32_t)compressed[off + 3] << 8)
+                 + (uint32_t)compressed[off + 4]);
          off += 5;
 
          /* This is the main LZMA decode loop.  */
@@ -6198,10 +6204,10 @@ elf_uncompress_lzma_block (const unsigned char 
*compressed,
          return 0;
        }
       computed_crc = elf_crc32 (0, uncompressed, uncompressed_offset);
-      stream_crc = (compressed[off]
-                   | (compressed[off + 1] << 8)
-                   | (compressed[off + 2] << 16)
-                   | (compressed[off + 3] << 24));
+      stream_crc = ((uint32_t)compressed[off]
+                   | ((uint32_t)compressed[off + 1] << 8)
+                   | ((uint32_t)compressed[off + 2] << 16)
+                   | ((uint32_t)compressed[off + 3] << 24));
       if (computed_crc != stream_crc)
        {
          elf_uncompress_failed ();
@@ -6336,10 +6342,10 @@ elf_uncompress_lzma (struct backtrace_state *state,
 
   /* Before that is the size of the index field, which precedes the
      footer.  */
-  index_size = (compressed[offset - 4]
-               | (compressed[offset - 3] << 8)
-               | (compressed[offset - 2] << 16)
-               | (compressed[offset - 1] << 24));
+  index_size = ((size_t)compressed[offset - 4]
+               | ((size_t)compressed[offset - 3] << 8)
+               | ((size_t)compressed[offset - 2] << 16)
+               | ((size_t)compressed[offset - 1] << 24));
   index_size = (index_size + 1) * 4;
   offset -= 4;
 

Reply via email to