diff options
author | Nick Clifton <nickc@redhat.com> | 2016-08-08 09:34:32 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2016-08-08 09:34:32 +0100 |
commit | db9537d2b735300b129e2715012ae249ee015f58 (patch) | |
tree | 7f70ed0274b797fd4ea8f4c92458ab7ae3d77ed8 /binutils | |
parent | f091cf02943c1ef8667742d28a8db82d0748f908 (diff) | |
download | gdb-db9537d2b735300b129e2715012ae249ee015f58.zip gdb-db9537d2b735300b129e2715012ae249ee015f58.tar.gz gdb-db9537d2b735300b129e2715012ae249ee015f58.tar.bz2 |
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.
Diffstat (limited to 'binutils')
-rw-r--r-- | binutils/ChangeLog | 6 | ||||
-rw-r--r-- | binutils/dwarf.c | 72 |
2 files changed, 61 insertions, 17 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 9aef046..2ba1bbd 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2016-08-08 Nick Clifton <nickc@redhat.com> + + 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 <nickc@redhat.com> PR binutils/17512 diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 282e069..2f2d8ae 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 = _("<unknown>"); + else if (ix > n_directories) + { + warn (_("directory index %u > number of directories %u\n"), ix, n_directories); + directory = _("<corrupt>"); + } + 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 <over large file table index %u>"), 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 <over large directory table entry %u>\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 = _("<corrupt>"); + } + else + fileName = (char *) file_table[indx].name; + } else - fileName = "<unknown>"; + fileName = _("<unknown>"); fileNameLength = strlen (fileName); |