From dcc050c86c3e5160497da7aab480adae9ba284aa Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Wed, 11 Mar 2020 11:17:39 +0000 Subject: [PATCH] gdb: Fix out of bounds array access in buildsym_compunit::record_line 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 | 5 +++++ gdb/buildsym.c | 19 +++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5c3d740a32..5e8fb71cd4 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2020-03-11 Andrew Burgess + + * 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 * dwarf2/loc.c (dwarf2_evaluate_property): Handle NULL frame in diff --git a/gdb/buildsym.c b/gdb/buildsym.c index 24aeba8e25..7155db34b0 100644 --- a/gdb/buildsym.c +++ b/gdb/buildsym.c @@ -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)