Avoid segfault on invalid directory table
authorPádraig Brady <pbrady@fb.com>
Fri, 24 Mar 2017 15:12:53 +0000 (15:12 +0000)
committerPedro Alves <palves@redhat.com>
Fri, 24 Mar 2017 15:12:53 +0000 (15:12 +0000)
gdb was segfaulting during backtrace on a binary here, where
fe->dir_index parsed from the DWARF info was seen to access beyond the
provided include_dirs array.

This commit bounds the access to entries actually written to the
array, and was verified to output the backtrace correctly.

gdb/ChangeLog:

* dwarf2read.c (setup_type_unit_groups): Ensure dir_index doesn't
reference beyond the 'lh->include_dirs' array before accessing to
it.
(psymtab_include_file_name): Likewise.
(dwarf_decode_lines_1): Likewise.
(dwarf_decode_lines): Likewise.
(file_file_name): Likewise.

gdb/ChangeLog
gdb/dwarf2read.c

index 5ad7ac3..dd12d3c 100644 (file)
@@ -1,3 +1,13 @@
+2017-03-24  Pádraig Brady  <pbrady@fb.com>
+
+       * dwarf2read.c (setup_type_unit_groups): Ensure dir_index doesn't
+       reference beyond the 'lh->include_dirs' array before accessing to
+       it.
+       (psymtab_include_file_name): Likewise.
+       (dwarf_decode_lines_1): Likewise.
+       (dwarf_decode_lines): Likewise.
+       (file_file_name): Likewise.
+
 2017-03-23  Simon Marchi  <simon.marchi@ericsson.com>
 
        * fbsd-tdep.c (fbsd_corefile_thread): Don't set/restore
index b3ea52b..519550b 100644 (file)
@@ -9416,7 +9416,8 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
          const char *dir = NULL;
          struct file_entry *fe = &lh->file_names[i];
 
-         if (fe->dir_index && lh->include_dirs != NULL)
+         if (fe->dir_index && lh->include_dirs != NULL
+             && (fe->dir_index - 1) < lh->num_include_dirs)
            dir = lh->include_dirs[fe->dir_index - 1];
          dwarf2_start_subfile (fe->name, dir);
 
@@ -17985,7 +17986,8 @@ psymtab_include_file_name (const struct line_header *lh, int file_index,
   char *copied_name = NULL;
   int file_is_pst;
 
-  if (fe.dir_index && lh->include_dirs != NULL)
+  if (fe.dir_index && lh->include_dirs != NULL
+      && (fe.dir_index - 1) < lh->num_include_dirs)
     dir_name = lh->include_dirs[fe.dir_index - 1];
 
   if (!IS_ABSOLUTE_PATH (include_name)
@@ -18366,7 +18368,8 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
           struct file_entry *fe = &lh->file_names[state_machine.file - 1];
           const char *dir = NULL;
 
-          if (fe->dir_index && lh->include_dirs != NULL)
+          if (fe->dir_index && lh->include_dirs != NULL
+              && (fe->dir_index - 1) < lh->num_include_dirs)
             dir = lh->include_dirs[fe->dir_index - 1];
 
          dwarf2_start_subfile (fe->name, dir);
@@ -18529,7 +18532,8 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
                else
                  {
                    fe = &lh->file_names[state_machine.file - 1];
-                   if (fe->dir_index && lh->include_dirs != NULL)
+                   if (fe->dir_index && lh->include_dirs != NULL
+                       && (fe->dir_index - 1) < lh->num_include_dirs)
                      dir = lh->include_dirs[fe->dir_index - 1];
                    if (record_lines_p)
                      {
@@ -18671,7 +18675,8 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
          struct file_entry *fe;
 
          fe = &lh->file_names[i];
-         if (fe->dir_index && lh->include_dirs != NULL)
+         if (fe->dir_index && lh->include_dirs != NULL
+             && (fe->dir_index - 1) < lh->num_include_dirs)
            dir = lh->include_dirs[fe->dir_index - 1];
          dwarf2_start_subfile (fe->name, dir);
 
@@ -21380,7 +21385,8 @@ file_file_name (int file, struct line_header *lh)
       struct file_entry *fe = &lh->file_names[file - 1];
 
       if (IS_ABSOLUTE_PATH (fe->name) || fe->dir_index == 0
-         || lh->include_dirs == NULL)
+         || lh->include_dirs == NULL
+         || (fe->dir_index - 1) >= lh->num_include_dirs)
         return xstrdup (fe->name);
       return concat (lh->include_dirs[fe->dir_index - 1], SLASH_STRING,
                     fe->name, (char *) NULL);