Patchwork libbacktrace patch committed: Fix leb128 overflow test

login
register
mail settings
Submitter Ian Taylor
Date Oct. 3, 2012, 10:07 p.m.
Message ID <mcrbogjxl9o.fsf@google.com>
Download mbox | patch
Permalink /patch/188940/
State New
Headers show

Comments

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

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))