aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2021-07-03 09:38:40 +0930
committerAlan Modra <amodra@gmail.com>2021-07-05 20:04:21 +0930
commit40e1d303cedca7d67f6219686f06b9750659beab (patch)
tree416c08ac006b675ef6da56119163e7100e7a1ed0
parent74ace054855321bc5271dd7b354131cd0b71333a (diff)
downloadbinutils-40e1d303cedca7d67f6219686f06b9750659beab.zip
binutils-40e1d303cedca7d67f6219686f06b9750659beab.tar.gz
binutils-40e1d303cedca7d67f6219686f06b9750659beab.tar.bz2
PR28047, readelf crash due to assertion failure
DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref1, and DW_FORM_ref_udata are all supposed to be within the containing unit. PR 28047 * dwarf.c (get_type_abbrev_from_form): Add cu_end parameter. Check DW_FORM_ref1 etc. arg against cu_end rather than end of section. Adjust all callers.
-rw-r--r--binutils/ChangeLog7
-rw-r--r--binutils/dwarf.c16
2 files changed, 17 insertions, 6 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 9efa39e..77b7ac7 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,10 @@
+2021-07-05 Alan Modra <amodra@gmail.com>
+
+ PR 28047
+ * dwarf.c (get_type_abbrev_from_form): Add cu_end parameter.
+ Check DW_FORM_ref1 etc. arg against cu_end rather than end of
+ section. Adjust all callers.
+
2021-07-03 Nick Clifton <nickc@redhat.com>
* configure: Regenerate.
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 1e7f4db..ad1ee97 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -2066,6 +2066,7 @@ static abbrev_entry *
get_type_abbrev_from_form (unsigned long form,
unsigned long uvalue,
dwarf_vma cu_offset,
+ unsigned char *cu_end,
const struct dwarf_section *section,
unsigned long *abbrev_num_return,
unsigned char **data_return,
@@ -2106,10 +2107,10 @@ get_type_abbrev_from_form (unsigned long form,
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
- if (uvalue + cu_offset > section->size)
+ if (uvalue + cu_offset > (size_t) (cu_end - section->start))
{
- warn (_("Unable to resolve ref form: uvalue %lx + cu_offset %lx > section size %lx\n"),
- uvalue, (long) cu_offset, (long) section->size);
+ warn (_("Unable to resolve ref form: uvalue %lx + cu_offset %lx > CU size %lx\n"),
+ uvalue, (long) cu_offset, (long) (cu_end - section->start));
return NULL;
}
uvalue += cu_offset;
@@ -2225,6 +2226,7 @@ get_type_signedness (abbrev_entry *entry,
type_abbrev = get_type_abbrev_from_form (attr->form,
uvalue,
cu_offset,
+ end,
section,
NULL /* abbrev num return */,
&type_data,
@@ -2963,8 +2965,10 @@ read_and_display_attr_value (unsigned long attribute,
unsigned char *type_data;
abbrev_map *map;
- type_abbrev = get_type_abbrev_from_form (form, uvalue, cu_offset,
- section, NULL, &type_data, &map);
+ type_abbrev = get_type_abbrev_from_form (form, uvalue,
+ cu_offset, end,
+ section, NULL,
+ &type_data, &map);
if (type_abbrev != NULL)
{
get_type_signedness (type_abbrev, section, type_data,
@@ -3297,7 +3301,7 @@ read_and_display_attr_value (unsigned long attribute,
unsigned long abbrev_number;
abbrev_entry *entry;
- entry = get_type_abbrev_from_form (form, uvalue, cu_offset,
+ entry = get_type_abbrev_from_form (form, uvalue, cu_offset, end,
section, & abbrev_number, NULL, NULL);
if (entry == NULL)
{