From db9537d2b735300b129e2715012ae249ee015f58 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Mon, 8 Aug 2016 09:34:32 +0100 Subject: Fix seg-fault in DWARF dumper when given a corrupt binary containing illegal directory and file table indicies. PR binutils/20439 * dwarf.c (display_debug_lines_decoded): Check directory and file indicies before using them to access directory and file tables. --- binutils/ChangeLog | 6 +++++ binutils/dwarf.c | 72 +++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 61 insertions(+), 17 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 9aef0468072..2ba1bbdf0e1 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2016-08-08 Nick Clifton + + PR binutils/20439 + * dwarf.c (display_debug_lines_decoded): Check directory and file + indicies before using them to access directory and file tables. + 2016-08-02 Nick Clifton PR binutils/17512 diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 282e069958d..2f2d8aea780 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -3334,7 +3334,20 @@ display_debug_lines_decoded (struct dwarf_section *section, else { unsigned int ix = file_table[0].directory_index; - const char *directory = ix ? (char *)directory_table[ix - 1] : "."; + const char *directory; + + if (ix == 0) + directory = "."; + /* PR 20439 */ + else if (n_directories == 0) + directory = _(""); + else if (ix > n_directories) + { + warn (_("directory index %u > number of directories %u\n"), ix, n_directories); + directory = _(""); + } + else + directory = (char *) directory_table[ix - 1]; if (do_wide || strlen (directory) < 76) printf (_("CU: %s/%s:\n"), directory, file_table[0].name); @@ -3492,20 +3505,35 @@ display_debug_lines_decoded (struct dwarf_section *section, data += bytes_read; state_machine_regs.file = adv; - if (file_table == NULL) - printf (_("\n [Use file table entry %d]\n"), state_machine_regs.file - 1); - else if (file_table[state_machine_regs.file - 1].directory_index == 0) - /* If directory index is 0, that means current directory. */ - printf ("\n./%s:[++]\n", - file_table[state_machine_regs.file - 1].name); - else if (directory_table == NULL) - printf (_("\n [Use directory table entry %d]\n"), - file_table[state_machine_regs.file - 1].directory_index - 1); - else - /* The directory index starts counting at 1. */ - printf ("\n%s/%s:\n", - directory_table[file_table[state_machine_regs.file - 1].directory_index - 1], - file_table[state_machine_regs.file - 1].name); + { + unsigned file = state_machine_regs.file - 1; + unsigned dir; + + if (file_table == NULL || n_files == 0) + printf (_("\n [Use file table entry %d]\n"), file); + /* PR 20439 */ + else if (file >= n_files) + { + warn (_("file index %u > number of files %u\n"), file + 1, n_files); + printf (_("\n "), file); + } + else if ((dir = file_table[file].directory_index) == 0) + /* If directory index is 0, that means current directory. */ + printf ("\n./%s:[++]\n", file_table[file].name); + else if (directory_table == NULL || n_directories == 0) + printf (_("\n [Use file %s in directory table entry %d]\n"), + file_table[file].name, dir); + /* PR 20439 */ + else if (dir > n_directories) + { + warn (_("directory index %u > number of directories %u\n"), dir, n_directories); + printf (_("\n \n"), dir); + } + else + printf ("\n%s/%s:\n", + /* The directory index starts counting at 1. */ + directory_table[dir - 1], file_table[file].name); + } break; case DW_LNS_set_column: @@ -3587,9 +3615,19 @@ display_debug_lines_decoded (struct dwarf_section *section, size_t fileNameLength; if (file_table) - fileName = (char *) file_table[state_machine_regs.file - 1].name; + { + unsigned indx = state_machine_regs.file - 1; + /* PR 20439 */ + if (indx >= n_files) + { + warn (_("corrupt file index %u encountered\n"), indx); + fileName = _(""); + } + else + fileName = (char *) file_table[indx].name; + } else - fileName = ""; + fileName = _(""); fileNameLength = strlen (fileName); -- cgit v1.2.1