ubsan: shift exponent 70 is too large
authorAlan Modra <amodra@gmail.com>
Sun, 15 Mar 2020 22:24:16 +0000 (08:54 +1030)
committerAlan Modra <amodra@gmail.com>
Mon, 16 Mar 2020 02:34:49 +0000 (13:04 +1030)
* unwind-ia64.c (unw_decode_uleb128): Prevent overlarge shifts.
Detect shift overflows and check that terminating byte is found.
Print an error on a bad uleb128.

binutils/ChangeLog
binutils/unwind-ia64.c

index 5f8af9468040748412ee8b925cd1dc167637e661..ee1534f98a649178ae44341ede99f2761a04c6d5 100644 (file)
@@ -1,3 +1,9 @@
+2020-03-16  Alan Modra  <amodra@gmail.com>
+
+       * unwind-ia64.c (unw_decode_uleb128): Prevent overlarge shifts.
+       Detect shift overflows and check that terminating byte is found.
+       Print an error on a bad uleb128.
+
 2020-03-14  Alan Modra  <amodra@gmail.com>
 
        * readelf.c (process_file): Clean ba_cache.
index b59a531e68583b61d3b3c163eaf9fb9714da629c..b9eae5bb21d468873a932bf86e257a906662415e 100644 (file)
@@ -544,21 +544,34 @@ static unw_word
 unw_decode_uleb128 (const unsigned char **dpp, const unsigned char * end)
 {
   unsigned shift = 0;
+  int status = 1;
   unw_word byte, result = 0;
   const unsigned char *bp = *dpp;
 
   while (bp < end)
     {
       byte = *bp++;
-      result |= (byte & 0x7f) << shift;
+      if (shift < sizeof (result) * 8)
+       {
+         result |= (byte & 0x7f) << shift;
+         if ((result >> shift) != (byte & 0x7f))
+           /* Overflow.  */
+           status |= 2;
+         shift += 7;
+       }
+      else if ((byte & 0x7f) != 0)
+       status |= 2;
 
       if ((byte & 0x80) == 0)
-       break;
-
-      shift += 7;
+       {
+         status &= ~1;
+         break;
+       }
     }
 
   *dpp = bp;
+  if (status != 0)
+    printf (_("Bad uleb128\n"));
 
   return result;
 }