Skip to content

Commit

Permalink
Sanity check loc_offsets index
Browse files Browse the repository at this point in the history
Fixes a segfault found by the fuzzers.

	* dwarf.c (fetch_indexed_value): Return -1 on error.
	(read_and_display_attr_value): Don't display string when
	fetch_indexed_value returns an error.  Sanity check loc_offsets
	index.
  • Loading branch information
amodra committed Aug 5, 2022
1 parent 188bc85 commit dfbc689
Showing 1 changed file with 20 additions and 10 deletions.
30 changes: 20 additions & 10 deletions binutils/dwarf.c
Original file line number Diff line number Diff line change
Expand Up @@ -779,7 +779,7 @@ fetch_indexed_addr (dwarf_vma offset, uint32_t num_bytes)

/* Fetch a value from a debug section that has been indexed by
something in another section (eg DW_FORM_loclistx or DW_FORM_rnglistx).
Returns 0 if the value could not be found. */
Returns -1 if the value could not be found. */

static dwarf_vma
fetch_indexed_value (dwarf_vma idx,
Expand All @@ -791,7 +791,7 @@ fetch_indexed_value (dwarf_vma idx,
if (section->start == NULL)
{
warn (_("Unable to locate %s section\n"), section->uncompressed_name);
return 0;
return -1;
}

uint32_t pointer_size, bias;
Expand Down Expand Up @@ -820,7 +820,7 @@ fetch_indexed_value (dwarf_vma idx,
{
warn (_("Offset into section %s too big: 0x%s\n"),
section->name, dwarf_vmatoa ("x", offset));
return 0;
return -1;
}

return byte_get (section->start + offset, pointer_size);
Expand Down Expand Up @@ -2782,7 +2782,8 @@ read_and_display_attr_value (unsigned long attribute,
if (dwo)
{
idx = fetch_indexed_value (uvalue, loclists_dwo, 0);
idx += (offset_size == 8) ? 20 : 12;
if (idx != (dwarf_vma) -1)
idx += (offset_size == 8) ? 20 : 12;
}
else if (debug_info_p == NULL)
{
Expand All @@ -2795,15 +2796,22 @@ read_and_display_attr_value (unsigned long attribute,
idx += debug_info_p->loclists_base;
Fortunately we already have that sum cached in the
loc_offsets array. */
idx = debug_info_p->loc_offsets [uvalue];
if (uvalue < debug_info_p->num_loc_offsets)
idx = debug_info_p->loc_offsets [uvalue];
else
{
warn (_("loc_offset %" PRIu64 " too big\n"), uvalue);
idx = -1;
}
}
}
else if (form == DW_FORM_rnglistx)
{
if (dwo)
{
idx = fetch_indexed_value (uvalue, rnglists_dwo, 0);
idx += (offset_size == 8) ? 20 : 12;
if (idx != (dwarf_vma) -1)
idx += (offset_size == 8) ? 20 : 12;
}
else
{
Expand All @@ -2814,7 +2822,8 @@ read_and_display_attr_value (unsigned long attribute,
/* We do not have a cached value this time, so we perform the
computation manually. */
idx = fetch_indexed_value (uvalue, rnglists, base);
idx += base;
if (idx != (dwarf_vma) -1)
idx += base;
}
}
else
Expand All @@ -2831,9 +2840,10 @@ read_and_display_attr_value (unsigned long attribute,
}

/* We have already displayed the form name. */
printf (_("%c(index: 0x%s): %s"), delimiter,
dwarf_vmatoa ("x", uvalue),
dwarf_vmatoa ("x", idx));
if (idx != (dwarf_vma) -1)
printf (_("%c(index: 0x%s): %s"), delimiter,
dwarf_vmatoa ("x", uvalue),
dwarf_vmatoa ("x", idx));
}
break;

Expand Down

0 comments on commit dfbc689

Please sign in to comment.