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.
This commit is contained in:
Nick Clifton 2016-08-08 09:34:32 +01:00
parent f091cf0294
commit db9537d2b7
2 changed files with 61 additions and 17 deletions

View file

@ -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

View file

@ -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);