libbacktrace patch committed: Fix leb128 overflow test

Submitted by Ian Taylor on Oct. 3, 2012, 10:07 p.m.

Details

Message ID mcrbogjxl9o.fsf@google.com
State New
Headers show

Commit Message

Ian Taylor Oct. 3, 2012, 10:07 p.m.
This patch to libbacktrace fixes the overflow test for the leb128
reading routines.  What matters is not the shift after the loop, but the
shift within the loop.  This also removes the setting of unit_buf.start
in build_address_map, which was simply wrong and was causing the error
message to print the wrong offset in the .debug_info section.
Bootstrapped and ran libbacktrace testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian


2012-10-03  Ian Lance Taylor  <iant@google.com>

	* dwarf.c (read_uleb128): Fix overflow test.
	(read_sleb128): Likewise.
	(build_address_map): Don't change unit_buf.start.

Patch hide | download patch | download mbox

Index: dwarf.c
===================================================================
--- dwarf.c	(revision 191858)
+++ dwarf.c	(working copy)
@@ -524,10 +524,12 @@  read_uleb128 (struct dwarf_buf *buf)
 {
   uint64_t ret;
   unsigned int shift;
+  int overflow;
   unsigned char b;
 
   ret = 0;
   shift = 0;
+  overflow = 0;
   do
     {
       const unsigned char *p;
@@ -536,14 +538,17 @@  read_uleb128 (struct dwarf_buf *buf)
       if (!advance (buf, 1))
 	return 0;
       b = *p;
-      ret |= ((uint64_t) (b & 0x7f)) << shift;
+      if (shift < 64)
+	ret |= ((uint64_t) (b & 0x7f)) << shift;
+      else if (!overflow)
+	{
+	  dwarf_buf_error (buf, "LEB128 overflows uint64_t");
+	  overflow = 1;
+	}
       shift += 7;
     }
   while ((b & 0x80) != 0);
 
-  if (shift > 64)
-    dwarf_buf_error (buf, "LEB128 overflows uint64_5");
-
   return ret;
 }
 
@@ -554,10 +559,12 @@  read_sleb128 (struct dwarf_buf *buf)
 {
   uint64_t val;
   unsigned int shift;
+  int overflow;
   unsigned char b;
 
   val = 0;
   shift = 0;
+  overflow = 0;
   do
     {
       const unsigned char *p;
@@ -566,15 +573,18 @@  read_sleb128 (struct dwarf_buf *buf)
       if (!advance (buf, 1))
 	return 0;
       b = *p;
-      val |= ((uint64_t) (b & 0x7f)) << shift;
+      if (shift < 64)
+	val |= ((uint64_t) (b & 0x7f)) << shift;
+      else if (!overflow)
+	{
+	  dwarf_buf_error (buf, "signed LEB128 overflows uint64_t");
+	  overflow = 1;
+	}
       shift += 7;
     }
   while ((b & 0x80) != 0);
 
-  if (shift > 64)
-    dwarf_buf_error (buf, "signed LEB128 overflows uint64_t");
-
-  if ((b & 0x40) != 0)
+  if ((b & 0x40) != 0 && shift < 64)
     val |= ((uint64_t) -1) << shift;
 
   return (int64_t) val;
@@ -1262,7 +1272,6 @@  build_address_map (struct backtrace_stat
 	}
 
       unit_buf = info;
-      unit_buf.start = info.buf;
       unit_buf.left = len;
 
       if (!advance (&info, len))