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.
This commit is contained in:
Alan Modra
2021-07-03 09:38:40 +09:30
parent 74ace05485
commit 40e1d303ce
2 changed files with 17 additions and 6 deletions

View File

@ -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> 2021-07-03 Nick Clifton <nickc@redhat.com>
* configure: Regenerate. * configure: Regenerate.

View File

@ -2066,6 +2066,7 @@ static abbrev_entry *
get_type_abbrev_from_form (unsigned long form, get_type_abbrev_from_form (unsigned long form,
unsigned long uvalue, unsigned long uvalue,
dwarf_vma cu_offset, dwarf_vma cu_offset,
unsigned char *cu_end,
const struct dwarf_section *section, const struct dwarf_section *section,
unsigned long *abbrev_num_return, unsigned long *abbrev_num_return,
unsigned char **data_return, unsigned char **data_return,
@ -2106,10 +2107,10 @@ get_type_abbrev_from_form (unsigned long form,
case DW_FORM_ref4: case DW_FORM_ref4:
case DW_FORM_ref8: case DW_FORM_ref8:
case DW_FORM_ref_udata: 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"), warn (_("Unable to resolve ref form: uvalue %lx + cu_offset %lx > CU size %lx\n"),
uvalue, (long) cu_offset, (long) section->size); uvalue, (long) cu_offset, (long) (cu_end - section->start));
return NULL; return NULL;
} }
uvalue += cu_offset; uvalue += cu_offset;
@ -2225,6 +2226,7 @@ get_type_signedness (abbrev_entry *entry,
type_abbrev = get_type_abbrev_from_form (attr->form, type_abbrev = get_type_abbrev_from_form (attr->form,
uvalue, uvalue,
cu_offset, cu_offset,
end,
section, section,
NULL /* abbrev num return */, NULL /* abbrev num return */,
&type_data, &type_data,
@ -2963,8 +2965,10 @@ read_and_display_attr_value (unsigned long attribute,
unsigned char *type_data; unsigned char *type_data;
abbrev_map *map; abbrev_map *map;
type_abbrev = get_type_abbrev_from_form (form, uvalue, cu_offset, type_abbrev = get_type_abbrev_from_form (form, uvalue,
section, NULL, &type_data, &map); cu_offset, end,
section, NULL,
&type_data, &map);
if (type_abbrev != NULL) if (type_abbrev != NULL)
{ {
get_type_signedness (type_abbrev, section, type_data, get_type_signedness (type_abbrev, section, type_data,
@ -3297,7 +3301,7 @@ read_and_display_attr_value (unsigned long attribute,
unsigned long abbrev_number; unsigned long abbrev_number;
abbrev_entry *entry; 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); section, & abbrev_number, NULL, NULL);
if (entry == NULL) if (entry == NULL)
{ {