This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
protect agains bogus debug data
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: binutils at sources dot redhat dot com
- Date: Fri, 26 Jan 2007 12:50:54 +0000
- Subject: protect agains bogus debug data
I had occasion to debug an executable with bogus dwarf information.
Unfortunately it caused readelf to segfault, which was less than helpful.
Current binutils didn't segfault, but that was only by fortuitous accident of
using 64bit offsets and therefore a < compare aborted a loop, rather than
wandering off into the weeds.
This patch protects the dwarf info printer by checking that the comp unit's
length and the abbrev offsets are sane.
I couldn't find a #define to format a dwarf_size_type, hence the icky cast to
unsigned long in the warnings. I guess I'd be happy if it didn't print out the
length -- after all that can be discovered by examining the section headers.
tested on i686-pc-linux-gnu and powerpc-wrs-vxworks, ok?
nathan
--
Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery
nathan@codesourcery.com :: http://www.planetfall.pwp.blueyonder.co.uk
2007-01-26 Nathan Sidwell <nathan@codesourcery.com>
* dwarf.c (process_debug_info): Protect against bogus length and
abbrev offsets.
Index: dwarf.c
===================================================================
RCS file: /cvs/src/src/binutils/dwarf.c,v
retrieving revision 1.8
diff -c -3 -p -r1.8 dwarf.c
*** dwarf.c 10 Oct 2006 10:45:45 -0000 1.8
--- dwarf.c 26 Jan 2007 12:42:01 -0000
*************** process_debug_info (struct dwarf_section
*** 1604,1610 ****
hdrptr += 2;
cu_offset = start - section_begin;
- start += compunit.cu_length + initial_length_size;
cu_abbrev_offset_ptr = hdrptr;
compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size);
--- 1604,1609 ----
*************** process_debug_info (struct dwarf_section
*** 1628,1635 ****
debug_information [unit].num_range_lists = 0;
}
- tags = hdrptr;
-
if (!do_loc)
{
printf (_(" Compilation Unit @ offset 0x%lx:\n"), cu_offset);
--- 1627,1632 ----
*************** process_debug_info (struct dwarf_section
*** 1639,1644 ****
--- 1636,1651 ----
printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size);
}
+ if (cu_offset + compunit.cu_length + initial_length_size
+ > section->size)
+ {
+ warn (_("Debug info is corrupted, length is invalid (section is %lu bytes)\n"),
+ (unsigned long)section->size);
+ break;
+ }
+ tags = hdrptr;
+ start += compunit.cu_length + initial_length_size;
+
if (compunit.cu_version != 2 && compunit.cu_version != 3)
{
warn (_("Only version 2 and 3 DWARF debug information is currently supported.\n"));
*************** process_debug_info (struct dwarf_section
*** 1649,1659 ****
/* Process the abbrevs used by this compilation unit. DWARF
sections under Mach-O have non-zero addresses. */
! process_abbrev_section
! ((unsigned char *) debug_displays [abbrev].section.start
! + compunit.cu_abbrev_offset - debug_displays [abbrev].section.address,
! (unsigned char *) debug_displays [abbrev].section.start
! + debug_displays [abbrev].section.size);
level = 0;
while (tags < start)
--- 1656,1670 ----
/* Process the abbrevs used by this compilation unit. DWARF
sections under Mach-O have non-zero addresses. */
! if (compunit.cu_abbrev_offset >= debug_displays [abbrev].section.size)
! warn (_("Debug info is corrupted, abbrev offset is invalid (section is %lu bytes)\n"),
! (unsigned long)debug_displays [abbrev].section.size);
! else
! process_abbrev_section
! ((unsigned char *) debug_displays [abbrev].section.start
! + compunit.cu_abbrev_offset - debug_displays [abbrev].section.address,
! (unsigned char *) debug_displays [abbrev].section.start
! + debug_displays [abbrev].section.size);
level = 0;
while (tags < start)