mirror of
https://git.yoctoproject.org/poky
synced 2026-03-12 02:09:39 +01:00
Affects: <= 2.29.1 (From OE-Core rev: 349b3cfb39c76304e351481899de9f72e4f1295b) Signed-off-by: Armin Kuster <akuster@mvista.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
228 lines
7.2 KiB
Diff
228 lines
7.2 KiB
Diff
From 52a93b95ec0771c97e26f0bb28630a271a667bd2 Mon Sep 17 00:00:00 2001
|
|
From: Alan Modra <amodra@gmail.com>
|
|
Date: Sun, 24 Sep 2017 14:37:16 +0930
|
|
Subject: [PATCH] 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.
|
|
|
|
Upstream-Status: Backport
|
|
Affects: <= 2.29.1
|
|
CVE: CVE-2017-15024
|
|
Signed-off-by: Armin Kuster <akuster@mvista.com>
|
|
|
|
---
|
|
bfd/ChangeLog | 10 ++++++++
|
|
bfd/dwarf2.c | 76 +++++++++++++++++++++++++++++++++++++++--------------------
|
|
2 files changed, 61 insertions(+), 25 deletions(-)
|
|
|
|
Index: git/bfd/dwarf2.c
|
|
===================================================================
|
|
--- git.orig/bfd/dwarf2.c
|
|
+++ git/bfd/dwarf2.c
|
|
@@ -2823,9 +2823,11 @@ lookup_symbol_in_variable_table (struct
|
|
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;
|
|
@@ -2835,7 +2837,7 @@ find_abstract_instance_name (struct comp
|
|
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. */
|
|
@@ -2844,7 +2846,12 @@ find_abstract_instance_name (struct comp
|
|
/* 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;
|
|
@@ -2879,9 +2886,10 @@ find_abstract_instance_name (struct comp
|
|
_bfd_error_handler
|
|
(_("Dwarf Error: Unable to read alt ref %u."), 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 ? */
|
|
@@ -2904,6 +2912,7 @@ find_abstract_instance_name (struct comp
|
|
_bfd_error_handler
|
|
(_("Dwarf Error: Could not find abbrev number %u."), abbrev_number);
|
|
bfd_set_error (bfd_error_bad_value);
|
|
+ return FALSE;
|
|
}
|
|
else
|
|
{
|
|
@@ -2913,6 +2922,15 @@ find_abstract_instance_name (struct comp
|
|
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:
|
|
@@ -2926,7 +2944,9 @@ find_abstract_instance_name (struct comp
|
|
}
|
|
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:
|
|
@@ -2944,7 +2964,8 @@ find_abstract_instance_name (struct comp
|
|
}
|
|
}
|
|
}
|
|
- return name;
|
|
+ *pname = name;
|
|
+ return TRUE;
|
|
}
|
|
|
|
static bfd_boolean
|
|
@@ -3005,20 +3026,22 @@ scan_unit_for_symbols (struct comp_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;
|
|
@@ -3076,13 +3099,13 @@ scan_unit_for_symbols (struct comp_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
|
|
{
|
|
@@ -3102,12 +3125,13 @@ scan_unit_for_symbols (struct comp_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;
|
|
|
|
@@ -3126,8 +3150,10 @@ scan_unit_for_symbols (struct comp_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:
|
|
@@ -3254,17 +3280,17 @@ scan_unit_for_symbols (struct comp_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;
|
|
}
|
|
}
|
|
|