public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* PR29948, heap-buffer-overflow in display_debug_lines_decoded
@ 2022-12-30 11:54 Alan Modra
  0 siblings, 0 replies; only message in thread
From: Alan Modra @ 2022-12-30 11:54 UTC (permalink / raw)
  To: binutils

This fixes a couple of places in display_debug_lines_decoded that were
off by one in checking DWARF5 .debug_line directory indices.  It also
displays the DWARF5 entry 0 for the program current directory rather
than "." as is done for pre-DWARF5.  I decided against displaying
DW_AT_comp_dir for pre-DWARF5 since I figure it is better for readelf
to minimally interpret debug info.

binutils/
	PR 29948
	* dwarf.c (display_debug_lines_decoded): Display the given
	directory entry 0 for DWARF5.  Properly check directory index
	against number of entries in the table.  Revert to using
	unsigned int for n_directories and associated variables.
	Correct warning messages.
gas/
	* testsuite/gas/elf/dwarf-5-loc0.d: Update.

diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index a00568dd3d8..cac26ad9c25 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -4899,7 +4899,7 @@ display_debug_lines_decoded (struct dwarf_section *  section,
       File_Entry *file_table = NULL;
       unsigned int n_files = 0;
       char **directory_table = NULL;
-      uint64_t n_directories = 0;
+      unsigned int n_directories = 0;
 
       if (startswith (section->name, ".debug_line.")
 	  /* Note: the following does not apply to .debug_line.dwo sections.
@@ -4949,8 +4949,8 @@ display_debug_lines_decoded (struct dwarf_section *  section,
 
 	  if (linfo.li_version >= 5)
 	    {
-	      unsigned char *format_start, format_count, *format;
-	      uint64_t formati, entryi;
+	      unsigned char *format_start, *format;
+	      unsigned int format_count, formati, entryi;
 
 	      load_debug_section_with_follow (line_str, fileptr);
 
@@ -5218,22 +5218,25 @@ display_debug_lines_decoded (struct dwarf_section *  section,
 	      unsigned int ix = file_table[0].directory_index;
 	      const char *directory;
 
-	      if (ix == 0)
+	      if (ix == 0 && linfo.li_version < 5)
 		directory = ".";
 	      /* PR 20439 */
 	      else if (n_directories == 0)
 		directory = _("<unknown>");
-	      else if (ix > n_directories)
+	      else
 		{
-		  warn (_("directory index %u > number of directories %" PRIu64 "\n"),
-			ix, n_directories);
-		  directory = _("<corrupt>");
+		  if (linfo.li_version < 5)
+		    --ix;
+		  if (ix >= n_directories)
+		    {
+		      warn (_("directory index %u "
+			      ">= number of directories %u\n"),
+			    ix, n_directories);
+		      directory = _("<corrupt>");
+		    }
+		  else
+		    directory = directory_table[ix];
 		}
-	      else if (linfo.li_version >= 5)
-		directory = directory_table[ix];
-	      else
-		directory = directory_table[ix - 1];
-
 	      if (do_wide)
 		printf (_("CU: %s/%s:\n"),
 			null_name (directory),
@@ -5397,45 +5400,53 @@ display_debug_lines_decoded (struct dwarf_section *  section,
 		READ_ULEB (uladv, data, end);
 		state_machine_regs.file = uladv;
 
-		{
-		  unsigned file = state_machine_regs.file;
-		  unsigned dir;
-
-		  if (linfo.li_version < 5)
-		    --file;
+		unsigned file = state_machine_regs.file;
+		if (linfo.li_version < 5)
+		  --file;
 
-		  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, 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", null_name (file_table[file].name));
-		  else if (directory_table == NULL || n_directories == 0)
-		    printf (_("\n [Use file %s in directory table entry %d]\n"),
-			    null_name (file_table[file].name), dir);
-		  /* PR 20439 */
-		  else if (dir > n_directories)
-		    {
-		      warn (_("directory index %u > number of directories %" PRIu64 "\n"),
-			    dir, n_directories);
-		      printf (_("\n <over large directory table entry %u>\n"), dir);
-		    }
-		  else if (linfo.li_version >= 5)
-		    printf ("\n%s/%s:\n",
-			    /* The directory index starts counting at 0.  */
-			    null_name (directory_table[dir]),
-			    null_name (file_table[file].name));
-		  else
-		    printf ("\n%s/%s:\n",
-			    /* The directory index starts counting at 1.  */
-			    null_name (directory_table[dir - 1]),
-			    null_name (file_table[file].name));
-		}
+		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, n_files);
+		    printf (_("\n <over large file table index %u>"), file);
+		  }
+		else
+		  {
+		    unsigned dir = file_table[file].directory_index;
+		    if (dir == 0 && linfo.li_version < 5)
+		      /* If directory index is 0, that means compilation
+			 current directory.  bfd/dwarf2.c shows
+			 DW_AT_comp_dir here but in keeping with the
+			 readelf practice of minimal interpretation of
+			 file data, we show "./".  */
+		      printf ("\n./%s:[++]\n",
+			      null_name (file_table[file].name));
+		    else if (directory_table == NULL || n_directories == 0)
+		      printf (_("\n [Use file %s "
+				"in directory table entry %d]\n"),
+			      null_name (file_table[file].name), dir);
+		    else
+		      {
+			if (linfo.li_version < 5)
+			  --dir;
+			/* PR 20439 */
+			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",
+				  null_name (directory_table[dir]),
+				  null_name (file_table[file].name));
+		      }
+		  }
 		break;
 
 	      case DW_LNS_set_column:
@@ -5530,7 +5541,8 @@ display_debug_lines_decoded (struct dwarf_section *  section,
 		  /* PR 20439  */
 		  if (indx >= n_files)
 		    {
-		      warn (_("corrupt file index %u encountered\n"), indx);
+		      warn (_("file index %u >= number of files %u\n"),
+			    indx, n_files);
 		      fileName = _("<corrupt>");
 		    }
 		  else
diff --git a/gas/testsuite/gas/elf/dwarf-5-loc0.d b/gas/testsuite/gas/elf/dwarf-5-loc0.d
index 7e8473a486f..9439d103b1f 100644
--- a/gas/testsuite/gas/elf/dwarf-5-loc0.d
+++ b/gas/testsuite/gas/elf/dwarf-5-loc0.d
@@ -7,10 +7,10 @@
 
 Contents of the \.debug_line section:
 
-CU: \./foo\.c:
+CU: .*/gas/testsuite/foo\.c:
 File name +Line number +Starting address +View +Stmt
 
-\./foo.c:\[\+\+\]
+.*/gas/testsuite/foo.c:
 foo\.c +1 +0x8 +x
 foo\.c +2 +0x10 +x
 foo\.c +- +0x10

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-12-30 11:54 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-30 11:54 PR29948, heap-buffer-overflow in display_debug_lines_decoded Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).