This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Fix seg-fault in DWARF dumper when given a corrupt binary containing illegal directory and file tabl


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=db9537d2b735300b129e2715012ae249ee015f58

commit db9537d2b735300b129e2715012ae249ee015f58
Author: Nick Clifton <nickc@redhat.com>
Date:   Mon Aug 8 09:34:32 2016 +0100

    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.

Diff:
---
 binutils/ChangeLog |  6 +++++
 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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]