[PR,symtab/17890] punt if dwarf line header version > 4

Message ID yjt2r3uek4fi.fsf@ruffy.mtv.corp.google.com
State New, archived
Headers

Commit Message

Doug Evans Jan. 28, 2015, 8:58 p.m. UTC
  Hi.

This patch is to stop gdb from trying to read a dwarf line header
that it doesn't understand.
If the version has changed the header fields may be in different
places and gdb could be reading gibberish.
E.g, the new version 5 header or the Two Level Linetable header.

Now what will happen is that gdb will just ignore the line table.
The user won't get line numbers but we can't help that.
At least gdb won't crash (or go into an infinite loop - pr 17891).

I plan to check this into the main tree and the 7.9 branch.
Regression tested on amd64-linux, and with a toolchain that
generates an unsupported line header.

Note: I could have made the test similar to binutils/dwarf.c:

  if (linfo->li_version != 2
      && linfo->li_version != 3
      && linfo->li_version != 4)

I opted to be conservative and not break something if a user
just happened to be using a broken toolchain that emits
version 0 or 1 but is still usable by gdb.
I'm more than happy to be more strict though!

2015-01-28  Doug Evans  <dje@google.com>

	PR symtab/17890
	* dwarf2read.c (dwarf_decode_line_header): Punt if version > 4.
  

Comments

Joel Brobecker Jan. 29, 2015, 4:43 a.m. UTC | #1
> I opted to be conservative and not break something if a user
> just happened to be using a broken toolchain that emits
> version 0 or 1 but is still usable by gdb.
> I'm more than happy to be more strict though!

FWIW, I think it's a valid concern. We can always revisit later
if we happen to see something that requires us to be stricter.

> 2015-01-28  Doug Evans  <dje@google.com>
> 
> 	PR symtab/17890
> 	* dwarf2read.c (dwarf_decode_line_header): Punt if version > 4.

LGTM.
  
Doug Evans Jan. 29, 2015, 6:35 p.m. UTC | #2
On Wed, Jan 28, 2015 at 8:43 PM, Joel Brobecker <brobecker@adacore.com> wrote:
>> I opted to be conservative and not break something if a user
>> just happened to be using a broken toolchain that emits
>> version 0 or 1 but is still usable by gdb.
>> I'm more than happy to be more strict though!
>
> FWIW, I think it's a valid concern. We can always revisit later
> if we happen to see something that requires us to be stricter.
>
>> 2015-01-28  Doug Evans  <dje@google.com>
>>
>>       PR symtab/17890
>>       * dwarf2read.c (dwarf_decode_line_header): Punt if version > 4.
>
> LGTM.

Thanks, committed to trunk and gdb-7.9-branch.
  

Patch

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 715b090..cd24d5e 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -17123,6 +17123,8 @@  get_debug_line_section (struct dwarf2_cu *cu)
 /* Read the statement program header starting at OFFSET in
    .debug_line, or .debug_line.dwo.  Return a pointer
    to a struct line_header, allocated using xmalloc.
+   Returns NULL if there is a problem reading the header, e.g., if it
+   has a version we don't understand.
 
    NOTE: the strings in the include directory and file name tables of
    the returned object point into the dwarf line section buffer,
@@ -17187,6 +17189,14 @@  dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
   lh->statement_program_end = line_ptr + lh->total_length;
   lh->version = read_2_bytes (abfd, line_ptr);
   line_ptr += 2;
+  if (lh->version > 4)
+    {
+      /* This is a version we don't understand.  The format could have
+	 changed in ways we don't handle properly so just punt.  */
+      complaint (&symfile_complaints,
+		 _("unsupported version in .debug_line section"));
+      return NULL;
+    }
   lh->header_length = read_offset_1 (abfd, line_ptr, offset_size);
   line_ptr += offset_size;
   lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);