Fix more memory faults uncovered by fuzzing various executables.
PR binutils/17512 * dwarf.c (read_and_display_attr_value): Check that we do not read past end. (display_debug_pubnames_worker): Add range checks. (process_debug_info): Check for invalid pointer sizes. (display_loc_list): Likewise. (display_loc_list_dwo): Likewise. (display_debug_ranges): Likewise. (display_debug_aranges): Check for invalid address size. (read_cie): Add range checks. Replace call strchr with while loop. * objdump.c (dump_dwarf): Replace abort with a warning message. (print_section_stabs): Improve range checks. * rdcoff.c (coff_get_slot): Use long for indx parameter type. Add check for an excesively large index. * rddbg.c (read_section_stabs_debugging_info): Zero terminate the string table. Avoid walking off the end of the stabs data. * stabs.c (parse_stab_string): Add check for a NULL name. PR binutils/17512 * coffcode.h (coff_slurp_line_table): Set the line number of corrupt entries to -1. (coff_slurp_symbol_table): Alway initialise the value of the symbol. * coffgen.c (coff_print_symbol): Check that the combined pointer is valid. (coff_print_symbol): Do not print negative line numbers. * peXXigen.c (pe_print_idata): Add range checking displaying member names.
This commit is contained in:
parent
40e91bc71f
commit
f41e4712a7
10 changed files with 244 additions and 82 deletions
144
binutils/dwarf.c
144
binutils/dwarf.c
|
@ -399,7 +399,7 @@ process_extended_line_op (unsigned char * data,
|
|||
|
||||
if (len == 0 || data == end)
|
||||
{
|
||||
warn (_("badly formed extended line op encountered!\n"));
|
||||
warn (_("Badly formed extended line op encountered!\n"));
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
|
@ -1464,9 +1464,9 @@ read_and_display_attr_value (unsigned long attribute,
|
|||
unsigned char * orig_data = data;
|
||||
unsigned int bytes_read;
|
||||
|
||||
if (data == end && form != DW_FORM_flag_present)
|
||||
if (data > end || (data == end && form != DW_FORM_flag_present))
|
||||
{
|
||||
warn (_("corrupt attribute\n"));
|
||||
warn (_("Corrupt attribute\n"));
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -1623,6 +1623,12 @@ read_and_display_attr_value (unsigned long attribute,
|
|||
case DW_FORM_exprloc:
|
||||
uvalue = read_uleb128 (data, & bytes_read, end);
|
||||
block_start = data + bytes_read;
|
||||
/* PR 17512: file: 008-103549-0.001:0.1. */
|
||||
if (block_start + uvalue > end)
|
||||
{
|
||||
warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
|
||||
uvalue = end - block_start;
|
||||
}
|
||||
if (do_loc)
|
||||
data = block_start + uvalue;
|
||||
else
|
||||
|
@ -1632,6 +1638,11 @@ read_and_display_attr_value (unsigned long attribute,
|
|||
case DW_FORM_block1:
|
||||
SAFE_BYTE_GET (uvalue, data, 1, end);
|
||||
block_start = data + 1;
|
||||
if (block_start + uvalue > end)
|
||||
{
|
||||
warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
|
||||
uvalue = end - block_start;
|
||||
}
|
||||
if (do_loc)
|
||||
data = block_start + uvalue;
|
||||
else
|
||||
|
@ -1641,6 +1652,11 @@ read_and_display_attr_value (unsigned long attribute,
|
|||
case DW_FORM_block2:
|
||||
SAFE_BYTE_GET (uvalue, data, 2, end);
|
||||
block_start = data + 2;
|
||||
if (block_start + uvalue > end)
|
||||
{
|
||||
warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
|
||||
uvalue = end - block_start;
|
||||
}
|
||||
if (do_loc)
|
||||
data = block_start + uvalue;
|
||||
else
|
||||
|
@ -1650,6 +1666,11 @@ read_and_display_attr_value (unsigned long attribute,
|
|||
case DW_FORM_block4:
|
||||
SAFE_BYTE_GET (uvalue, data, 4, end);
|
||||
block_start = data + 4;
|
||||
if (block_start + uvalue > end)
|
||||
{
|
||||
warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
|
||||
uvalue = end - block_start;
|
||||
}
|
||||
if (do_loc)
|
||||
data = block_start + uvalue;
|
||||
else
|
||||
|
@ -2184,7 +2205,7 @@ process_debug_info (struct dwarf_section *section,
|
|||
|
||||
if (num_units == 0)
|
||||
{
|
||||
error (_("No comp units in %s section ?"), section->name);
|
||||
error (_("No comp units in %s section ?\n"), section->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2193,7 +2214,7 @@ process_debug_info (struct dwarf_section *section,
|
|||
sizeof (* debug_information));
|
||||
if (debug_information == NULL)
|
||||
{
|
||||
error (_("Not enough memory for a debug info array of %u entries"),
|
||||
error (_("Not enough memory for a debug info array of %u entries\n"),
|
||||
num_units);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2271,6 +2292,13 @@ process_debug_info (struct dwarf_section *section,
|
|||
}
|
||||
|
||||
SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end);
|
||||
/* PR 17512: file: 001-108546-0.001:0.1. */
|
||||
if (compunit.cu_pointer_size < 2 || compunit.cu_pointer_size > 8)
|
||||
{
|
||||
warn (_("Invalid pointer size (%d) in compunit header, using %d instead\n"),
|
||||
compunit.cu_pointer_size, offset_size);
|
||||
compunit.cu_pointer_size = offset_size;
|
||||
}
|
||||
|
||||
if (do_types)
|
||||
{
|
||||
|
@ -2602,20 +2630,20 @@ read_debug_line_header (struct dwarf_section * section,
|
|||
SAFE_BYTE_GET_AND_INC (linfo->li_length, hdrptr, 4, end);
|
||||
|
||||
if (linfo->li_length == 0xffffffff)
|
||||
{
|
||||
/* This section is 64-bit DWARF 3. */
|
||||
{
|
||||
/* This section is 64-bit DWARF 3. */
|
||||
SAFE_BYTE_GET_AND_INC (linfo->li_length, hdrptr, 8, end);
|
||||
offset_size = 8;
|
||||
initial_length_size = 12;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset_size = 4;
|
||||
initial_length_size = 4;
|
||||
}
|
||||
offset_size = 8;
|
||||
initial_length_size = 12;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset_size = 4;
|
||||
initial_length_size = 4;
|
||||
}
|
||||
|
||||
if (linfo->li_length + initial_length_size > section->size)
|
||||
{
|
||||
{
|
||||
/* If the length is just a bias against the initial_length_size then
|
||||
this means that the field has a relocation against it which has not
|
||||
been applied. (Ie we are dealing with an object file, not a linked
|
||||
|
@ -2627,11 +2655,10 @@ read_debug_line_header (struct dwarf_section * section,
|
|||
}
|
||||
else
|
||||
{
|
||||
warn (_("The line info appears to be corrupt - "
|
||||
"the section is too small\n"));
|
||||
warn (_("The line info appears to be corrupt - the section is too small\n"));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get and check the version number. */
|
||||
SAFE_BYTE_GET_AND_INC (linfo->li_version, hdrptr, 2, end);
|
||||
|
@ -2639,25 +2666,25 @@ read_debug_line_header (struct dwarf_section * section,
|
|||
if (linfo->li_version != 2
|
||||
&& linfo->li_version != 3
|
||||
&& linfo->li_version != 4)
|
||||
{
|
||||
warn (_("Only DWARF version 2, 3 and 4 line info is currently supported.\n"));
|
||||
{
|
||||
warn (_("Only DWARF version 2, 3 and 4 line info is currently supported.\n"));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_BYTE_GET_AND_INC (linfo->li_prologue_length, hdrptr, offset_size, end);
|
||||
SAFE_BYTE_GET_AND_INC (linfo->li_min_insn_length, hdrptr, 1, end);
|
||||
|
||||
if (linfo->li_version >= 4)
|
||||
{
|
||||
{
|
||||
SAFE_BYTE_GET_AND_INC (linfo->li_max_ops_per_insn, hdrptr, 1, end);
|
||||
|
||||
if (linfo->li_max_ops_per_insn == 0)
|
||||
{
|
||||
warn (_("Invalid maximum operations per insn.\n"));
|
||||
{
|
||||
warn (_("Invalid maximum operations per insn.\n"));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
linfo->li_max_ops_per_insn = 1;
|
||||
|
||||
SAFE_BYTE_GET_AND_INC (linfo->li_default_is_stmt, hdrptr, 1, end);
|
||||
|
@ -3204,7 +3231,7 @@ display_debug_lines_decoded (struct dwarf_section *section,
|
|||
|
||||
if (ext_op_code_len == 0)
|
||||
{
|
||||
warn (_("badly formed extended line op encountered!\n"));
|
||||
warn (_("Badly formed extended line op encountered!\n"));
|
||||
break;
|
||||
}
|
||||
ext_op_code_len += bytes_read;
|
||||
|
@ -3598,11 +3625,17 @@ display_debug_pubnames_worker (struct dwarf_section *section,
|
|||
|
||||
do
|
||||
{
|
||||
bfd_size_type maxprint;
|
||||
|
||||
SAFE_BYTE_GET (offset, data, offset_size, end);
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
data += offset_size;
|
||||
if (data >= end)
|
||||
break;
|
||||
maxprint = (end - data) - 1;
|
||||
|
||||
if (is_gnu)
|
||||
{
|
||||
unsigned int kind_data;
|
||||
|
@ -3612,6 +3645,7 @@ display_debug_pubnames_worker (struct dwarf_section *section,
|
|||
|
||||
SAFE_BYTE_GET (kind_data, data, 1, end);
|
||||
data++;
|
||||
maxprint --;
|
||||
/* GCC computes the kind as the upper byte in the CU index
|
||||
word, and then right shifts it by the CU index size.
|
||||
Left shift KIND to where the gdb-index.h accessor macros
|
||||
|
@ -3620,13 +3654,16 @@ display_debug_pubnames_worker (struct dwarf_section *section,
|
|||
kind = GDB_INDEX_SYMBOL_KIND_VALUE (kind_data);
|
||||
kind_name = get_gdb_index_symbol_kind_name (kind);
|
||||
is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (kind_data);
|
||||
printf (" %-6lx %s,%-10s %s\n",
|
||||
printf (" %-6lx %s,%-10s %.*s\n",
|
||||
offset, is_static ? _("s") : _("g"),
|
||||
kind_name, data);
|
||||
kind_name, (int) maxprint, data);
|
||||
}
|
||||
else
|
||||
printf (" %-6lx\t%s\n", offset, data);
|
||||
data += strnlen ((char *) data, end - data) + 1;
|
||||
printf (" %-6lx\t%.*s\n", offset, (int) maxprint, data);
|
||||
|
||||
data += strnlen ((char *) data, maxprint) + 1;
|
||||
if (data >= end)
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (offset != 0);
|
||||
|
@ -4135,6 +4172,13 @@ display_loc_list (struct dwarf_section *section,
|
|||
unsigned short length;
|
||||
int need_frame_base;
|
||||
|
||||
if (pointer_size < 2 || pointer_size > 8)
|
||||
{
|
||||
warn (_("Invalid pointer size (%d) in debug info for entry %d\n"),
|
||||
pointer_size, debug_info_entry);
|
||||
return;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (start + 2 * pointer_size > section_end)
|
||||
|
@ -4247,6 +4291,13 @@ display_loc_list_dwo (struct dwarf_section *section,
|
|||
unsigned int idx;
|
||||
unsigned int bytes_read;
|
||||
|
||||
if (pointer_size < 2 || pointer_size > 8)
|
||||
{
|
||||
warn (_("Invalid pointer size (%d) in debug info for entry %d\n"),
|
||||
pointer_size, debug_info_entry);
|
||||
return;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
printf (" %8.8lx ", offset + (start - *start_ptr));
|
||||
|
@ -4647,7 +4698,8 @@ display_debug_aranges (struct dwarf_section *section,
|
|||
|
||||
address_size = arange.ar_pointer_size + arange.ar_segment_size;
|
||||
|
||||
if (address_size == 0)
|
||||
/* PR 17512: file: 001-108546-0.001:0.1. */
|
||||
if (address_size == 0 || address_size > 8)
|
||||
{
|
||||
error (_("Invalid address size in %s section!\n"),
|
||||
section->name);
|
||||
|
@ -4886,11 +4938,18 @@ display_debug_ranges (struct dwarf_section *section,
|
|||
unsigned long base_address;
|
||||
|
||||
pointer_size = debug_info_p->pointer_size;
|
||||
|
||||
offset = range_entry->ranges_offset;
|
||||
next = section_begin + offset;
|
||||
base_address = debug_info_p->base_address;
|
||||
|
||||
/* PR 17512: file: 001-101485-0.001:0.1. */
|
||||
if (pointer_size < 2 || pointer_size > 8)
|
||||
{
|
||||
warn (_("Corrupt pointer size (%d) in debug entry at offset %8.8lx\n"),
|
||||
pointer_size, offset);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dwarf_check != 0 && i > 0)
|
||||
{
|
||||
if (start < next)
|
||||
|
@ -5243,6 +5302,10 @@ read_cie (unsigned char *start, unsigned char *end,
|
|||
unsigned char *augmentation_data = NULL;
|
||||
unsigned long augmentation_data_len = 0;
|
||||
|
||||
/* PR 17512: file: 001-228113-0.004. */
|
||||
if (start >= end)
|
||||
return end;
|
||||
|
||||
fc = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
|
||||
memset (fc, 0, sizeof (Frame_Chunk));
|
||||
|
||||
|
@ -5252,7 +5315,16 @@ read_cie (unsigned char *start, unsigned char *end,
|
|||
version = *start++;
|
||||
|
||||
fc->augmentation = (char *) start;
|
||||
start = (unsigned char *) strchr ((char *) start, '\0') + 1;
|
||||
/* PR 17512: file: 001-228113-0.004.
|
||||
Skip past augmentation name, but avoid running off the end of the data. */
|
||||
while (start < end)
|
||||
if (* start ++ == '\0')
|
||||
break;
|
||||
if (start == end)
|
||||
{
|
||||
warn (_("No terminator for augmentation name\n"));
|
||||
return start;
|
||||
}
|
||||
|
||||
if (strcmp (fc->augmentation, "eh") == 0)
|
||||
start += eh_addr_size;
|
||||
|
@ -6140,7 +6212,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
if (op >= DW_CFA_lo_user && op <= DW_CFA_hi_user)
|
||||
printf (_(" DW_CFA_??? (User defined call frame op: %#x)\n"), op);
|
||||
else
|
||||
warn (_("unsupported or unknown Dwarf Call Frame Instruction number: %#x\n"), op);
|
||||
warn (_("Unsupported or unknown Dwarf Call Frame Instruction number: %#x\n"), op);
|
||||
start = block_end;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue