Fix a potential illegal memory access when parsing corrupt DWARF information.
authorNick Clifton <nickc@redhat.com>
Fri, 16 Dec 2022 12:06:43 +0000 (12:06 +0000)
committerNick Clifton <nickc@redhat.com>
Fri, 16 Dec 2022 12:06:43 +0000 (12:06 +0000)
PR 29908
* dwarf.c (display_debug_addr): Check for corrupt header lengths.

binutils/ChangeLog
binutils/dwarf.c

index 6ec81ebd0998ad7f1fcb723569e9c9d1bdb338c9..16bddf73c07e57530e091ab903627e852cabd699 100644 (file)
@@ -1,3 +1,8 @@
+2022-12-16  Nick Clifton  <nickc@redhat.com>
+
+       PR 29908
+       * dwarf.c (display_debug_addr): Check for corrupt header lengths.
+
 2022-12-01  Nick Clifton  <nickc@redhat.com>
 
        PR 25202
index 33ee41cb6c948d5f6601302ff0bf3946ee0aeead..533f118301271e8a373e812ab123665a747a1a93 100644 (file)
@@ -7738,6 +7738,12 @@ display_debug_addr (struct dwarf_section *section,
              return 0;
            }
          end = curr_header + length;
+         if (end < entry)
+           {
+             warn (_("Corrupt %s section header: length field (%lx) is too small\n"),
+                   section->name, length);
+             return 0;
+           }
          SAFE_BYTE_GET_AND_INC (version, curr_header, 2, entry);
          if (version != 5)
            warn (_("Corrupt %s section: expecting version number 5 in header but found %d instead\n"),
@@ -7748,9 +7754,22 @@ display_debug_addr (struct dwarf_section *section,
          address_size += segment_selector_size;
        }
       else
-       end = section->start + debug_addr_info [i + 1]->addr_base;
+       {
+         end = section->start + debug_addr_info [i + 1]->addr_base;
+
+         if (end < entry)
+           {
+             warn (_("Corrupt %s section: address base of entry %u (%lx) is less than entry %u (%lx)\n"),
+                   section->name,
+                   i, debug_addr_info [i]->addr_base,
+                   i + 1, debug_addr_info [i + 1]->addr_base);
+             return 0;
+           }
+       }
+
       header = end;
       idx = 0;
+
       while ((size_t) (end - entry) >= address_size)
        {
          uint64_t base = byte_get (entry, address_size);