PR28047, readelf crash due to assertion failure

Message ID YOLrpNWZRBwFiD25@squeak.grove.modra.org
State New
Headers show
Series
  • PR28047, readelf crash due to assertion failure
Related show

Commit Message

Libor Bukata via Binutils July 5, 2021, 11:23 a.m.
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.


-- 
Alan Modra
Australia Development Lab, IBM

Patch

diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 1e7f4db7b7c..ad1ee97d9bf 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)
 	  {