PR27849, heap-buffer-overflow on readelf -w
authorAlan Modra <amodra@gmail.com>
Tue, 11 May 2021 23:21:22 +0000 (08:51 +0930)
committerAlan Modra <amodra@gmail.com>
Wed, 12 May 2021 06:11:10 +0000 (15:41 +0930)
PR 27849
* dwarf.c (fetch_indexed_string): Correct length sanity checks.
Sanity check section size for version and padding too.  Correct
index sanity check.  Handle multiple tables in .debug_str_offsets.

binutils/ChangeLog
binutils/dwarf.c

index 242563ed3a5332acecd9c5656b100e6eb3ad85af..9e0611ea9f47aef91980eb9d8011b882a30b63a3 100644 (file)
@@ -1,3 +1,10 @@
+2021-05-12  Alan Modra  <amodra@gmail.com>
+
+       PR 27849
+       * dwarf.c (fetch_indexed_string): Correct length sanity checks.
+       Sanity check section size for version and padding too.  Correct
+       index sanity check.  Handle multiple tables in .debug_str_offsets.
+
 2021-05-11  Hans-Peter Nilsson  <hp@axis.com>
 
        * dwarf.c (process_abbrev_set): Properly parenthesize before
index 8bc0acb270c2c2025553f0ac2896b86ac4865256..336a3d5839259484c58880e5d3862c62fe317162 100644 (file)
@@ -745,7 +745,7 @@ fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
   dwarf_vma str_offset;
   const char * ret;
   unsigned char *curr = index_section->start;
-  const unsigned char *end = curr + index_section->size;
+  unsigned char *end = curr + index_section->size;
   dwarf_vma length;
 
   if (index_section->start == NULL)
@@ -780,16 +780,31 @@ fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
     {
       /* Skip the version and padding bytes.
         We assume that they are correct.  */
-      curr += 4;
+      if (end - curr >= 4)
+       curr += 4;
+      else
+       curr = end;
+      if (length >= 4)
+       length -= 4;
+      else
+       length = 0;
+
+      if (this_set != NULL
+         && this_set->section_sizes[DW_SECT_STR_OFFSETS] < length)
+       length = this_set->section_sizes[DW_SECT_STR_OFFSETS];
 
-      /* FIXME: The code below assumes that there is only one table
-        in the .debug_str_offsets section, so check that now.  */
-      if ((offset_size == 4 && curr + length < (end - 8))
-         || (offset_size == 8 && curr + length < (end - 16)))
+      if (length > (dwarf_vma) (end - curr))
        {
-         warn (_("index table size is too small %s vs %s\n"),
+         warn (_("index table size too large for section %s vs %s\n"),
                dwarf_vmatoa ("x", length),
                dwarf_vmatoa ("x", index_section->size));
+         length = end - curr;
+       }
+
+      if (length < offset_size)
+       {
+         warn (_("index table size %s is too small\n"),
+               dwarf_vmatoa ("x", length));
          return _("<table too small>");
        }
     }
@@ -799,7 +814,8 @@ fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
   if (this_set != NULL)
     index_offset += this_set->section_offsets [DW_SECT_STR_OFFSETS];
 
-  if (index_offset >= length)
+  if (index_offset >= length
+      || length - index_offset < offset_size)
     {
       warn (_("DW_FORM_GNU_str_index offset too big: 0x%s vs 0x%s\n"),
            dwarf_vmatoa ("x", index_offset),