gdb: Fix out of bounds array access in buildsym_compunit::record_line
authorAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 11 Mar 2020 11:17:39 +0000 (11:17 +0000)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 11 Mar 2020 11:24:50 +0000 (11:24 +0000)
This commit:

  commit 8c95582da858ac981f689a6f599acacb8c5c490f
  Date:   Mon Dec 30 21:04:51 2019 +0000

      gdb: Add support for tracking the DWARF line table is-stmt field

Introduced an invalid memory access, by reading outside the bounds of
an array.

This would cause this valgrind error:

  ==7633== Invalid read of size 4
  ==7633==    at 0x4D002C: buildsym_compunit::record_line(subfile*, int, unsigned long, bool) (buildsym.c:688)
  ==7633==    by 0x5F60A5: dwarf_record_line_1(gdbarch*, subfile*, unsigned int, unsigned long, bool, dwarf2_cu*) (read.c:19956)
  ==7633==    by 0x5F63B0: lnp_state_machine::record_line(bool) (read.c:20024)
  ==7633==    by 0x5F5DD5: lnp_state_machine::handle_special_opcode(unsigned char) (read.c:19851)
  ==7633==    by 0x5F6706: dwarf_decode_lines_1(line_header*, dwarf2_cu*, int, unsigned long) (read.c:20135)
  ==7633==    by 0x5F6C57: dwarf_decode_lines(line_header*, char const*, dwarf2_cu*, dwarf2_psymtab*, unsigned long, int) (read.c:20328)
  ==7633==    by 0x5DF5F1: handle_DW_AT_stmt_list(die_info*, dwarf2_cu*, char const*, unsigned long) (read.c:10748)
  ==7633==    by 0x5DF823: read_file_scope(die_info*, dwarf2_cu*) (read.c:10796)
  ==7633==    by 0x5DDA63: process_die(die_info*, dwarf2_cu*) (read.c:9815)
  ==7633==    by 0x5DD44A: process_full_comp_unit(dwarf2_per_cu_data*, language) (read.c:9580)
  ==7633==    by 0x5DAB58: process_queue(dwarf2_per_objfile*) (read.c:8867)
  ==7633==    by 0x5CB30E: dw2_do_instantiate_symtab(dwarf2_per_cu_data*, bool) (read.c:2374)
  ==7633==  Address 0xa467f48 is 8 bytes before a block of size 16,024 alloc'd
  ==7633==    at 0x4C2CDCB: malloc (vg_replace_malloc.c:299)
  ==7633==    by 0x451FC4: xmalloc (alloc.c:60)
  ==7633==    by 0x4CFFDF: buildsym_compunit::record_line(subfile*, int, unsigned long, bool) (buildsym.c:678)
  ==7633==    by 0x5F60A5: dwarf_record_line_1(gdbarch*, subfile*, unsigned int, unsigned long, bool, dwarf2_cu*) (read.c:19956)
  ==7633==    by 0x5F63B0: lnp_state_machine::record_line(bool) (read.c:20024)
  ==7633==    by 0x5F5DD5: lnp_state_machine::handle_special_opcode(unsigned char) (read.c:19851)
  ==7633==    by 0x5F6706: dwarf_decode_lines_1(line_header*, dwarf2_cu*, int, unsigned long) (read.c:20135)
  ==7633==    by 0x5F6C57: dwarf_decode_lines(line_header*, char const*, dwarf2_cu*, dwarf2_psymtab*, unsigned long, int) (read.c:20328)
  ==7633==    by 0x5DF5F1: handle_DW_AT_stmt_list(die_info*, dwarf2_cu*, char const*, unsigned long) (read.c:10748)
  ==7633==    by 0x5DF823: read_file_scope(die_info*, dwarf2_cu*) (read.c:10796)
  ==7633==    by 0x5DDA63: process_die(die_info*, dwarf2_cu*) (read.c:9815)
  ==7633==    by 0x5DD44A: process_full_comp_unit(dwarf2_per_cu_data*, language) (read.c:9580)

gdb/ChangeLog:

* buildsyms.c (buildsym_compunit::record_line): Avoid accessing
previous item in the list, when the list has no items.

gdb/ChangeLog
gdb/buildsym.c

index 5c3d740a327b9f50264a15ee57ddff690d2c6bdd..5e8fb71cd4d5508d641fb97a4ce0d2fcac38282e 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-11  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * buildsyms.c (buildsym_compunit::record_line): Avoid accessing
+       previous item in the list, when the list has no items.
+
 2020-03-11  Tom de Vries  <tdevries@suse.de>
 
        * dwarf2/loc.c (dwarf2_evaluate_property): Handle NULL frame in
index 24aeba8e25220b80210e0d08b0a8badf6cd848af..7155db34b085c36ea3c4d599be8a2151c8bfa889 100644 (file)
@@ -681,15 +681,18 @@ buildsym_compunit::record_line (struct subfile *subfile, int line,
       m_have_line_numbers = true;
     }
 
-  /* If we have a duplicate for the previous entry then ignore the new
-     entry, except, if the new entry is setting the is_stmt flag, then
-     ensure the previous entry respects the new setting.  */
-  e = subfile->line_vector->item + subfile->line_vector->nitems - 1;
-  if (e->line == line && e->pc == pc)
+  if (subfile->line_vector->nitems > 0)
     {
-      if (is_stmt && !e->is_stmt)
-       e->is_stmt = 1;
-      return;
+      /* If we have a duplicate for the previous entry then ignore the new
+        entry, except, if the new entry is setting the is_stmt flag, then
+        ensure the previous entry respects the new setting.  */
+      e = subfile->line_vector->item + subfile->line_vector->nitems - 1;
+      if (e->line == line && e->pc == pc)
+       {
+         if (is_stmt && !e->is_stmt)
+           e->is_stmt = 1;
+         return;
+       }
     }
 
   if (subfile->line_vector->nitems + 1 >= subfile->line_vector_length)