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.
This commit is contained in:
Alan Modra 2017-09-24 14:37:16 +09:30
parent d8010d3e75
commit 52a93b95ec
2 changed files with 61 additions and 25 deletions

View File

@ -1,3 +1,13 @@
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

View File

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