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] PR22187, infinite loop in find_abstract_instance_name


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

commit 52a93b95ec0771c97e26f0bb28630a271a667bd2
Author: Alan Modra <amodra@gmail.com>
Date:   Sun Sep 24 14:37:16 2017 +0930

    PR22187, infinite loop in find_abstract_instance_name
    
    This patch prevents the simple case of infinite recursion in
    find_abstract_instance_name by ensuring that the attributes being
    processed are not the same as the previous call.
    
    The patch also does a little cleanup, and leaves in place some changes
    to the nested_funcs array that I made when I wrongly thought looping
    might occur in scan_unit_for_symbols.
    
    	PR 22187
    	* dwarf2.c (find_abstract_instance_name): Add orig_info_ptr and
    	pname param.  Return status.  Make name const.  Don't abort,
    	return an error.  Formatting.  Exit if current info_ptr matches
    	orig_info_ptr.  Update callers.
    	(scan_unit_for_symbols): Start at nesting_level of zero.  Make
    	nested_funcs an array of structs for extensibility.  Formatting.

Diff:
---
 bfd/ChangeLog | 10 ++++++++
 bfd/dwarf2.c  | 76 +++++++++++++++++++++++++++++++++++++++--------------------
 2 files changed, 61 insertions(+), 25 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index e232764..450217a 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,15 @@
 2017-09-24  Alan Modra  <amodra@gmail.com>
 
+	PR 22187
+	* dwarf2.c (find_abstract_instance_name): Add orig_info_ptr and
+	pname param.  Return status.  Make name const.  Don't abort,
+	return an error.  Formatting.  Exit if current info_ptr matches
+	orig_info_ptr.  Update callers.
+	(scan_unit_for_symbols): Start at nesting_level of zero.  Make
+	nested_funcs an array of structs for extensibility.  Formatting.
+
+2017-09-24  Alan Modra  <amodra@gmail.com>
+
 	PR 22186
 	* dwarf2.c (decode_line_info): Fail on lh.line_range of zero
 	rather than dividing by zero.
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 8b2281e..ec4c311 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -2826,9 +2826,11 @@ lookup_symbol_in_variable_table (struct comp_unit *unit,
   return FALSE;
 }
 
-static char *
+static bfd_boolean
 find_abstract_instance_name (struct comp_unit *unit,
+			     bfd_byte *orig_info_ptr,
 			     struct attribute *attr_ptr,
+			     const char **pname,
 			     bfd_boolean *is_linkage)
 {
   bfd *abfd = unit->abfd;
@@ -2838,7 +2840,7 @@ find_abstract_instance_name (struct comp_unit *unit,
   struct abbrev_info *abbrev;
   bfd_uint64_t die_ref = attr_ptr->u.val;
   struct attribute attr;
-  char *name = NULL;
+  const char *name = NULL;
 
   /* DW_FORM_ref_addr can reference an entry in a different CU. It
      is an offset from the .debug_info section, not the current CU.  */
@@ -2847,7 +2849,12 @@ find_abstract_instance_name (struct comp_unit *unit,
       /* We only support DW_FORM_ref_addr within the same file, so
 	 any relocations should be resolved already.  */
       if (!die_ref)
-	abort ();
+	{
+	  _bfd_error_handler
+	    (_("Dwarf Error: Abstract instance DIE ref zero."));
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
 
       info_ptr = unit->sec_info_ptr + die_ref;
       info_ptr_end = unit->end_ptr;
@@ -2883,9 +2890,10 @@ find_abstract_instance_name (struct comp_unit *unit,
 	    (_("Dwarf Error: Unable to read alt ref %llu."),
 	     (long long) die_ref);
 	  bfd_set_error (bfd_error_bad_value);
-	  return NULL;
+	  return FALSE;
 	}
-      info_ptr_end = unit->stash->alt_dwarf_info_buffer + unit->stash->alt_dwarf_info_size;
+      info_ptr_end = (unit->stash->alt_dwarf_info_buffer
+		      + unit->stash->alt_dwarf_info_size);
 
       /* FIXME: Do we need to locate the correct CU, in a similar
 	 fashion to the code in the DW_FORM_ref_addr case above ?  */
@@ -2908,6 +2916,7 @@ find_abstract_instance_name (struct comp_unit *unit,
 	  _bfd_error_handler
 	    (_("Dwarf Error: Could not find abbrev number %u."), abbrev_number);
 	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
 	}
       else
 	{
@@ -2917,6 +2926,15 @@ find_abstract_instance_name (struct comp_unit *unit,
 					 info_ptr, info_ptr_end);
 	      if (info_ptr == NULL)
 		break;
+	      /* It doesn't ever make sense for DW_AT_specification to
+		 refer to the same DIE.  Stop simple recursion.  */
+	      if (info_ptr == orig_info_ptr)
+		{
+		  _bfd_error_handler
+		    (_("Dwarf Error: Abstract instance recursion detected."));
+		  bfd_set_error (bfd_error_bad_value);
+		  return FALSE;
+		}
 	      switch (attr.name)
 		{
 		case DW_AT_name:
@@ -2930,7 +2948,9 @@ find_abstract_instance_name (struct comp_unit *unit,
 		    }
 		  break;
 		case DW_AT_specification:
-		  name = find_abstract_instance_name (unit, &attr, is_linkage);
+		  if (!find_abstract_instance_name (unit, info_ptr, &attr,
+						    pname, is_linkage))
+		    return FALSE;
 		  break;
 		case DW_AT_linkage_name:
 		case DW_AT_MIPS_linkage_name:
@@ -2948,7 +2968,8 @@ find_abstract_instance_name (struct comp_unit *unit,
 	    }
 	}
     }
-  return name;
+  *pname = name;
+  return TRUE;
 }
 
 static bfd_boolean
@@ -3009,20 +3030,22 @@ scan_unit_for_symbols (struct comp_unit *unit)
   bfd *abfd = unit->abfd;
   bfd_byte *info_ptr = unit->first_child_die_ptr;
   bfd_byte *info_ptr_end = unit->stash->info_ptr_end;
-  int nesting_level = 1;
-  struct funcinfo **nested_funcs;
+  int nesting_level = 0;
+  struct nest_funcinfo {
+    struct funcinfo *func;
+  } *nested_funcs;
   int nested_funcs_size;
 
   /* Maintain a stack of in-scope functions and inlined functions, which we
      can use to set the caller_func field.  */
   nested_funcs_size = 32;
-  nested_funcs = (struct funcinfo **)
-    bfd_malloc (nested_funcs_size * sizeof (struct funcinfo *));
+  nested_funcs = (struct nest_funcinfo *)
+    bfd_malloc (nested_funcs_size * sizeof (*nested_funcs));
   if (nested_funcs == NULL)
     return FALSE;
-  nested_funcs[nesting_level] = 0;
+  nested_funcs[nesting_level].func = 0;
 
-  while (nesting_level)
+  while (nesting_level >= 0)
     {
       unsigned int abbrev_number, bytes_read, i;
       struct abbrev_info *abbrev;
@@ -3080,13 +3103,13 @@ scan_unit_for_symbols (struct comp_unit *unit)
 	  BFD_ASSERT (!unit->cached);
 
 	  if (func->tag == DW_TAG_inlined_subroutine)
-	    for (i = nesting_level - 1; i >= 1; i--)
-	      if (nested_funcs[i])
+	    for (i = nesting_level; i-- != 0; )
+	      if (nested_funcs[i].func)
 		{
-		  func->caller_func = nested_funcs[i];
+		  func->caller_func = nested_funcs[i].func;
 		  break;
 		}
-	  nested_funcs[nesting_level] = func;
+	  nested_funcs[nesting_level].func = func;
 	}
       else
 	{
@@ -3106,12 +3129,13 @@ scan_unit_for_symbols (struct comp_unit *unit)
 	    }
 
 	  /* No inline function in scope at this nesting level.  */
-	  nested_funcs[nesting_level] = 0;
+	  nested_funcs[nesting_level].func = 0;
 	}
 
       for (i = 0; i < abbrev->num_attrs; ++i)
 	{
-	  info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, info_ptr_end);
+	  info_ptr = read_attribute (&attr, &abbrev->attrs[i],
+				     unit, info_ptr, info_ptr_end);
 	  if (info_ptr == NULL)
 	    goto fail;
 
@@ -3130,8 +3154,10 @@ scan_unit_for_symbols (struct comp_unit *unit)
 
 		case DW_AT_abstract_origin:
 		case DW_AT_specification:
-		  func->name = find_abstract_instance_name (unit, &attr,
-							    &func->is_linkage);
+		  if (!find_abstract_instance_name (unit, info_ptr, &attr,
+						    &func->name,
+						    &func->is_linkage))
+		    goto fail;
 		  break;
 
 		case DW_AT_name:
@@ -3257,17 +3283,17 @@ scan_unit_for_symbols (struct comp_unit *unit)
 
 	  if (nesting_level >= nested_funcs_size)
 	    {
-	      struct funcinfo **tmp;
+	      struct nest_funcinfo *tmp;
 
 	      nested_funcs_size *= 2;
-	      tmp = (struct funcinfo **)
+	      tmp = (struct nest_funcinfo *)
 		bfd_realloc (nested_funcs,
-			     nested_funcs_size * sizeof (struct funcinfo *));
+			     nested_funcs_size * sizeof (*nested_funcs));
 	      if (tmp == NULL)
 		goto fail;
 	      nested_funcs = tmp;
 	    }
-	  nested_funcs[nesting_level] = 0;
+	  nested_funcs[nesting_level].func = 0;
 	}
     }


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