summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2016-08-08 09:34:32 +0100
committerNick Clifton <nickc@redhat.com>2016-08-08 09:34:32 +0100
commitdb9537d2b735300b129e2715012ae249ee015f58 (patch)
tree7f70ed0274b797fd4ea8f4c92458ab7ae3d77ed8
parentf091cf02943c1ef8667742d28a8db82d0748f908 (diff)
downloadbinutils-gdb-db9537d2b735300b129e2715012ae249ee015f58.tar.gz
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.
-rw-r--r--binutils/ChangeLog6
-rw-r--r--binutils/dwarf.c72
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 <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 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 = _("<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);