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
|
@ -1,3 +1,16 @@
|
||||||
|
2014-11-12 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
2014-11-12 Alan Modra <amodra@gmail.com>
|
2014-11-12 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
PR binutils/17512
|
PR binutils/17512
|
||||||
|
|
|
@ -4510,7 +4510,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
|
||||||
unsigned int counter;
|
unsigned int counter;
|
||||||
alent *cache_ptr;
|
alent *cache_ptr;
|
||||||
bfd_vma prev_offset = 0;
|
bfd_vma prev_offset = 0;
|
||||||
int ordered = 1;
|
bfd_boolean ordered = TRUE;
|
||||||
unsigned int nbr_func;
|
unsigned int nbr_func;
|
||||||
LINENO *src;
|
LINENO *src;
|
||||||
bfd_boolean have_func;
|
bfd_boolean have_func;
|
||||||
|
@ -4561,6 +4561,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
|
||||||
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
||||||
(_("%B: warning: illegal symbol index 0x%lx in line number entry %d"),
|
(_("%B: warning: illegal symbol index 0x%lx in line number entry %d"),
|
||||||
abfd, (long) symndx, counter);
|
abfd, (long) symndx, counter);
|
||||||
|
cache_ptr->line_number = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4572,11 +4573,12 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
|
||||||
|
|
||||||
/* PR 17512 file: 078-10659-0.004 */
|
/* PR 17512 file: 078-10659-0.004 */
|
||||||
if (sym < obj_symbols (abfd)
|
if (sym < obj_symbols (abfd)
|
||||||
|| sym >= obj_symbols (abfd) + obj_raw_syment_count (abfd))
|
|| sym >= obj_symbols (abfd) + bfd_get_symcount (abfd))
|
||||||
{
|
{
|
||||||
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
||||||
(_("%B: warning: illegal symbol in line number entry %d"),
|
(_("%B: warning: illegal symbol in line number entry %d"),
|
||||||
abfd, counter);
|
abfd, counter);
|
||||||
|
cache_ptr->line_number = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4590,7 +4592,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
|
||||||
|
|
||||||
sym->lineno = cache_ptr;
|
sym->lineno = cache_ptr;
|
||||||
if (sym->symbol.value < prev_offset)
|
if (sym->symbol.value < prev_offset)
|
||||||
ordered = 0;
|
ordered = FALSE;
|
||||||
prev_offset = sym->symbol.value;
|
prev_offset = sym->symbol.value;
|
||||||
}
|
}
|
||||||
else if (!have_func)
|
else if (!have_func)
|
||||||
|
@ -4625,6 +4627,8 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
|
||||||
if (lineno_cache[i].line_number == 0)
|
if (lineno_cache[i].line_number == 0)
|
||||||
*p++ = &lineno_cache[i];
|
*p++ = &lineno_cache[i];
|
||||||
|
|
||||||
|
BFD_ASSERT ((p - func_table) == nbr_func);
|
||||||
|
|
||||||
/* Sort by functions. */
|
/* Sort by functions. */
|
||||||
qsort (func_table, nbr_func, sizeof (alent *), coff_sort_func_alent);
|
qsort (func_table, nbr_func, sizeof (alent *), coff_sort_func_alent);
|
||||||
|
|
||||||
|
@ -4650,6 +4654,8 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
|
||||||
*n_cache_ptr++ = *old_ptr++;
|
*n_cache_ptr++ = *old_ptr++;
|
||||||
while (old_ptr->line_number != 0);
|
while (old_ptr->line_number != 0);
|
||||||
}
|
}
|
||||||
|
BFD_ASSERT ((bfd_size_type) (n_cache_ptr - n_lineno_cache) == (amt / sizeof (alent)));
|
||||||
|
|
||||||
memcpy (lineno_cache, n_lineno_cache, amt);
|
memcpy (lineno_cache, n_lineno_cache, amt);
|
||||||
}
|
}
|
||||||
bfd_release (abfd, func_table);
|
bfd_release (abfd, func_table);
|
||||||
|
@ -4710,6 +4716,8 @@ coff_slurp_symbol_table (bfd * abfd)
|
||||||
dst->symbol.section = coff_section_from_bfd_index (abfd,
|
dst->symbol.section = coff_section_from_bfd_index (abfd,
|
||||||
src->u.syment.n_scnum);
|
src->u.syment.n_scnum);
|
||||||
dst->symbol.flags = 0;
|
dst->symbol.flags = 0;
|
||||||
|
/* PR 17512: file: 079-7098-0.001:0.1. */
|
||||||
|
dst->symbol.value = 0;
|
||||||
dst->done_lineno = FALSE;
|
dst->done_lineno = FALSE;
|
||||||
|
|
||||||
switch (src->u.syment.n_sclass)
|
switch (src->u.syment.n_sclass)
|
||||||
|
|
|
@ -2099,6 +2099,14 @@ coff_print_symbol (bfd *abfd,
|
||||||
|
|
||||||
fprintf (file, "[%3ld]", (long) (combined - root));
|
fprintf (file, "[%3ld]", (long) (combined - root));
|
||||||
|
|
||||||
|
/* PR 17512: file: 079-33786-0.001:0.1. */
|
||||||
|
if (combined < obj_raw_syments (abfd)
|
||||||
|
|| combined >= obj_raw_syments (abfd) + obj_raw_syment_count (abfd))
|
||||||
|
{
|
||||||
|
fprintf (file, _("<corrupt info> %s"), symbol->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (! combined->fix_value)
|
if (! combined->fix_value)
|
||||||
val = (bfd_vma) combined->u.syment.n_value;
|
val = (bfd_vma) combined->u.syment.n_value;
|
||||||
else
|
else
|
||||||
|
@ -2192,8 +2200,11 @@ coff_print_symbol (bfd *abfd,
|
||||||
l++;
|
l++;
|
||||||
while (l->line_number)
|
while (l->line_number)
|
||||||
{
|
{
|
||||||
fprintf (file, "\n%4d : ", l->line_number);
|
if (l->line_number > 0)
|
||||||
bfd_fprintf_vma (abfd, file, l->u.offset + symbol->section->vma);
|
{
|
||||||
|
fprintf (file, "\n%4d : ", l->line_number);
|
||||||
|
bfd_fprintf_vma (abfd, file, l->u.offset + symbol->section->vma);
|
||||||
|
}
|
||||||
l++;
|
l++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1481,27 +1481,31 @@ pe_print_idata (bfd * abfd, void * vfile)
|
||||||
#ifdef COFF_WITH_pex64
|
#ifdef COFF_WITH_pex64
|
||||||
for (j = 0; idx + j + 8 <= datasize; j += 8)
|
for (j = 0; idx + j + 8 <= datasize; j += 8)
|
||||||
{
|
{
|
||||||
|
bfd_size_type amt;
|
||||||
unsigned long member = bfd_get_32 (abfd, data + idx + j);
|
unsigned long member = bfd_get_32 (abfd, data + idx + j);
|
||||||
unsigned long member_high = bfd_get_32 (abfd, data + idx + j + 4);
|
unsigned long member_high = bfd_get_32 (abfd, data + idx + j + 4);
|
||||||
|
|
||||||
if (!member && !member_high)
|
if (!member && !member_high)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
amt = member - adj;
|
||||||
|
|
||||||
if (HighBitSet (member_high))
|
if (HighBitSet (member_high))
|
||||||
fprintf (file, "\t%lx%08lx\t %4lx%08lx <none>",
|
fprintf (file, "\t%lx%08lx\t %4lx%08lx <none>",
|
||||||
member_high, member,
|
member_high, member,
|
||||||
WithoutHighBit (member_high), member);
|
WithoutHighBit (member_high), member);
|
||||||
/* PR binutils/17512: Handle corrupt PE data. */
|
/* PR binutils/17512: Handle corrupt PE data. */
|
||||||
else if ((bfd_vma) member - adj + 2 >= datasize)
|
else if (amt + 2 >= datasize)
|
||||||
fprintf (file, _("\t<corrupt: 0x%04lx>"), member);
|
fprintf (file, _("\t<corrupt: 0x%04lx>"), member);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int ordinal;
|
int ordinal;
|
||||||
char *member_name;
|
char *member_name;
|
||||||
|
|
||||||
ordinal = bfd_get_16 (abfd, data + member - adj);
|
ordinal = bfd_get_16 (abfd, data + amt);
|
||||||
member_name = (char *) data + member - adj + 2;
|
member_name = (char *) data + amt + 2;
|
||||||
fprintf (file, "\t%04lx\t %4d %s",member, ordinal, member_name);
|
fprintf (file, "\t%04lx\t %4d %.*s",member, ordinal,
|
||||||
|
(int) (datasize - (amt + 2)), member_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the time stamp is not zero, the import address
|
/* If the time stamp is not zero, the import address
|
||||||
|
@ -1517,27 +1521,30 @@ pe_print_idata (bfd * abfd, void * vfile)
|
||||||
#else
|
#else
|
||||||
for (j = 0; idx + j + 4 <= datasize; j += 4)
|
for (j = 0; idx + j + 4 <= datasize; j += 4)
|
||||||
{
|
{
|
||||||
|
bfd_size_type amt;
|
||||||
unsigned long member = bfd_get_32 (abfd, data + idx + j);
|
unsigned long member = bfd_get_32 (abfd, data + idx + j);
|
||||||
|
|
||||||
/* Print single IMAGE_IMPORT_BY_NAME vector. */
|
/* Print single IMAGE_IMPORT_BY_NAME vector. */
|
||||||
if (member == 0)
|
if (member == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
amt = member - adj;
|
||||||
if (HighBitSet (member))
|
if (HighBitSet (member))
|
||||||
fprintf (file, "\t%04lx\t %4lu <none>",
|
fprintf (file, "\t%04lx\t %4lu <none>",
|
||||||
member, WithoutHighBit (member));
|
member, WithoutHighBit (member));
|
||||||
/* PR binutils/17512: Handle corrupt PE data. */
|
/* PR binutils/17512: Handle corrupt PE data. */
|
||||||
else if ((bfd_vma) member - adj + 2 >= datasize)
|
else if (amt + 2 >= datasize)
|
||||||
fprintf (file, _("\t<corrupt: 0x%04lx>"), member);
|
fprintf (file, _("\t<corrupt: 0x%04lx>"), member);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int ordinal;
|
int ordinal;
|
||||||
char *member_name;
|
char *member_name;
|
||||||
|
|
||||||
ordinal = bfd_get_16 (abfd, data + member - adj);
|
ordinal = bfd_get_16 (abfd, data + amt);
|
||||||
member_name = (char *) data + member - adj + 2;
|
member_name = (char *) data + amt + 2;
|
||||||
fprintf (file, "\t%04lx\t %4d %s",
|
fprintf (file, "\t%04lx\t %4d %.*s",
|
||||||
member, ordinal, member_name);
|
member, ordinal,
|
||||||
|
(int) (datasize - (amt + 2)), member_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the time stamp is not zero, the import address
|
/* If the time stamp is not zero, the import address
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
2014-11-12 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
2014-11-11 Nick Clifton <nickc@redhat.com>
|
2014-11-11 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
PR binutils/17531
|
PR binutils/17531
|
||||||
|
|
144
binutils/dwarf.c
144
binutils/dwarf.c
|
@ -399,7 +399,7 @@ process_extended_line_op (unsigned char * data,
|
||||||
|
|
||||||
if (len == 0 || data == end)
|
if (len == 0 || data == end)
|
||||||
{
|
{
|
||||||
warn (_("badly formed extended line op encountered!\n"));
|
warn (_("Badly formed extended line op encountered!\n"));
|
||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1464,9 +1464,9 @@ read_and_display_attr_value (unsigned long attribute,
|
||||||
unsigned char * orig_data = data;
|
unsigned char * orig_data = data;
|
||||||
unsigned int bytes_read;
|
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;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1623,6 +1623,12 @@ read_and_display_attr_value (unsigned long attribute,
|
||||||
case DW_FORM_exprloc:
|
case DW_FORM_exprloc:
|
||||||
uvalue = read_uleb128 (data, & bytes_read, end);
|
uvalue = read_uleb128 (data, & bytes_read, end);
|
||||||
block_start = data + bytes_read;
|
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)
|
if (do_loc)
|
||||||
data = block_start + uvalue;
|
data = block_start + uvalue;
|
||||||
else
|
else
|
||||||
|
@ -1632,6 +1638,11 @@ read_and_display_attr_value (unsigned long attribute,
|
||||||
case DW_FORM_block1:
|
case DW_FORM_block1:
|
||||||
SAFE_BYTE_GET (uvalue, data, 1, end);
|
SAFE_BYTE_GET (uvalue, data, 1, end);
|
||||||
block_start = data + 1;
|
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)
|
if (do_loc)
|
||||||
data = block_start + uvalue;
|
data = block_start + uvalue;
|
||||||
else
|
else
|
||||||
|
@ -1641,6 +1652,11 @@ read_and_display_attr_value (unsigned long attribute,
|
||||||
case DW_FORM_block2:
|
case DW_FORM_block2:
|
||||||
SAFE_BYTE_GET (uvalue, data, 2, end);
|
SAFE_BYTE_GET (uvalue, data, 2, end);
|
||||||
block_start = data + 2;
|
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)
|
if (do_loc)
|
||||||
data = block_start + uvalue;
|
data = block_start + uvalue;
|
||||||
else
|
else
|
||||||
|
@ -1650,6 +1666,11 @@ read_and_display_attr_value (unsigned long attribute,
|
||||||
case DW_FORM_block4:
|
case DW_FORM_block4:
|
||||||
SAFE_BYTE_GET (uvalue, data, 4, end);
|
SAFE_BYTE_GET (uvalue, data, 4, end);
|
||||||
block_start = data + 4;
|
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)
|
if (do_loc)
|
||||||
data = block_start + uvalue;
|
data = block_start + uvalue;
|
||||||
else
|
else
|
||||||
|
@ -2184,7 +2205,7 @@ process_debug_info (struct dwarf_section *section,
|
||||||
|
|
||||||
if (num_units == 0)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2193,7 +2214,7 @@ process_debug_info (struct dwarf_section *section,
|
||||||
sizeof (* debug_information));
|
sizeof (* debug_information));
|
||||||
if (debug_information == NULL)
|
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);
|
num_units);
|
||||||
return 0;
|
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);
|
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)
|
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);
|
SAFE_BYTE_GET_AND_INC (linfo->li_length, hdrptr, 4, end);
|
||||||
|
|
||||||
if (linfo->li_length == 0xffffffff)
|
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);
|
SAFE_BYTE_GET_AND_INC (linfo->li_length, hdrptr, 8, end);
|
||||||
offset_size = 8;
|
offset_size = 8;
|
||||||
initial_length_size = 12;
|
initial_length_size = 12;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
offset_size = 4;
|
offset_size = 4;
|
||||||
initial_length_size = 4;
|
initial_length_size = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (linfo->li_length + initial_length_size > section->size)
|
if (linfo->li_length + initial_length_size > section->size)
|
||||||
{
|
{
|
||||||
/* If the length is just a bias against the initial_length_size then
|
/* 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
|
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
|
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
|
else
|
||||||
{
|
{
|
||||||
warn (_("The line info appears to be corrupt - "
|
warn (_("The line info appears to be corrupt - the section is too small\n"));
|
||||||
"the section is too small\n"));
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get and check the version number. */
|
/* Get and check the version number. */
|
||||||
SAFE_BYTE_GET_AND_INC (linfo->li_version, hdrptr, 2, end);
|
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
|
if (linfo->li_version != 2
|
||||||
&& linfo->li_version != 3
|
&& linfo->li_version != 3
|
||||||
&& linfo->li_version != 4)
|
&& 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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SAFE_BYTE_GET_AND_INC (linfo->li_prologue_length, hdrptr, offset_size, end);
|
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);
|
SAFE_BYTE_GET_AND_INC (linfo->li_min_insn_length, hdrptr, 1, end);
|
||||||
|
|
||||||
if (linfo->li_version >= 4)
|
if (linfo->li_version >= 4)
|
||||||
{
|
{
|
||||||
SAFE_BYTE_GET_AND_INC (linfo->li_max_ops_per_insn, hdrptr, 1, end);
|
SAFE_BYTE_GET_AND_INC (linfo->li_max_ops_per_insn, hdrptr, 1, end);
|
||||||
|
|
||||||
if (linfo->li_max_ops_per_insn == 0)
|
if (linfo->li_max_ops_per_insn == 0)
|
||||||
{
|
{
|
||||||
warn (_("Invalid maximum operations per insn.\n"));
|
warn (_("Invalid maximum operations per insn.\n"));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
linfo->li_max_ops_per_insn = 1;
|
linfo->li_max_ops_per_insn = 1;
|
||||||
|
|
||||||
SAFE_BYTE_GET_AND_INC (linfo->li_default_is_stmt, hdrptr, 1, end);
|
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)
|
if (ext_op_code_len == 0)
|
||||||
{
|
{
|
||||||
warn (_("badly formed extended line op encountered!\n"));
|
warn (_("Badly formed extended line op encountered!\n"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ext_op_code_len += bytes_read;
|
ext_op_code_len += bytes_read;
|
||||||
|
@ -3598,11 +3625,17 @@ display_debug_pubnames_worker (struct dwarf_section *section,
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
bfd_size_type maxprint;
|
||||||
|
|
||||||
SAFE_BYTE_GET (offset, data, offset_size, end);
|
SAFE_BYTE_GET (offset, data, offset_size, end);
|
||||||
|
|
||||||
if (offset != 0)
|
if (offset != 0)
|
||||||
{
|
{
|
||||||
data += offset_size;
|
data += offset_size;
|
||||||
|
if (data >= end)
|
||||||
|
break;
|
||||||
|
maxprint = (end - data) - 1;
|
||||||
|
|
||||||
if (is_gnu)
|
if (is_gnu)
|
||||||
{
|
{
|
||||||
unsigned int kind_data;
|
unsigned int kind_data;
|
||||||
|
@ -3612,6 +3645,7 @@ display_debug_pubnames_worker (struct dwarf_section *section,
|
||||||
|
|
||||||
SAFE_BYTE_GET (kind_data, data, 1, end);
|
SAFE_BYTE_GET (kind_data, data, 1, end);
|
||||||
data++;
|
data++;
|
||||||
|
maxprint --;
|
||||||
/* GCC computes the kind as the upper byte in the CU index
|
/* GCC computes the kind as the upper byte in the CU index
|
||||||
word, and then right shifts it by the CU index size.
|
word, and then right shifts it by the CU index size.
|
||||||
Left shift KIND to where the gdb-index.h accessor macros
|
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 = GDB_INDEX_SYMBOL_KIND_VALUE (kind_data);
|
||||||
kind_name = get_gdb_index_symbol_kind_name (kind);
|
kind_name = get_gdb_index_symbol_kind_name (kind);
|
||||||
is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (kind_data);
|
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"),
|
offset, is_static ? _("s") : _("g"),
|
||||||
kind_name, data);
|
kind_name, (int) maxprint, data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printf (" %-6lx\t%s\n", offset, data);
|
printf (" %-6lx\t%.*s\n", offset, (int) maxprint, data);
|
||||||
data += strnlen ((char *) data, end - data) + 1;
|
|
||||||
|
data += strnlen ((char *) data, maxprint) + 1;
|
||||||
|
if (data >= end)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (offset != 0);
|
while (offset != 0);
|
||||||
|
@ -4135,6 +4172,13 @@ display_loc_list (struct dwarf_section *section,
|
||||||
unsigned short length;
|
unsigned short length;
|
||||||
int need_frame_base;
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
if (start + 2 * pointer_size > section_end)
|
if (start + 2 * pointer_size > section_end)
|
||||||
|
@ -4247,6 +4291,13 @@ display_loc_list_dwo (struct dwarf_section *section,
|
||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
unsigned int bytes_read;
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
printf (" %8.8lx ", offset + (start - *start_ptr));
|
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;
|
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"),
|
error (_("Invalid address size in %s section!\n"),
|
||||||
section->name);
|
section->name);
|
||||||
|
@ -4886,11 +4938,18 @@ display_debug_ranges (struct dwarf_section *section,
|
||||||
unsigned long base_address;
|
unsigned long base_address;
|
||||||
|
|
||||||
pointer_size = debug_info_p->pointer_size;
|
pointer_size = debug_info_p->pointer_size;
|
||||||
|
|
||||||
offset = range_entry->ranges_offset;
|
offset = range_entry->ranges_offset;
|
||||||
next = section_begin + offset;
|
next = section_begin + offset;
|
||||||
base_address = debug_info_p->base_address;
|
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 (dwarf_check != 0 && i > 0)
|
||||||
{
|
{
|
||||||
if (start < next)
|
if (start < next)
|
||||||
|
@ -5243,6 +5302,10 @@ read_cie (unsigned char *start, unsigned char *end,
|
||||||
unsigned char *augmentation_data = NULL;
|
unsigned char *augmentation_data = NULL;
|
||||||
unsigned long augmentation_data_len = 0;
|
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));
|
fc = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
|
||||||
memset (fc, 0, sizeof (Frame_Chunk));
|
memset (fc, 0, sizeof (Frame_Chunk));
|
||||||
|
|
||||||
|
@ -5252,7 +5315,16 @@ read_cie (unsigned char *start, unsigned char *end,
|
||||||
version = *start++;
|
version = *start++;
|
||||||
|
|
||||||
fc->augmentation = (char *) 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)
|
if (strcmp (fc->augmentation, "eh") == 0)
|
||||||
start += eh_addr_size;
|
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)
|
if (op >= DW_CFA_lo_user && op <= DW_CFA_hi_user)
|
||||||
printf (_(" DW_CFA_??? (User defined call frame op: %#x)\n"), op);
|
printf (_(" DW_CFA_??? (User defined call frame op: %#x)\n"), op);
|
||||||
else
|
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;
|
start = block_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2388,7 +2388,12 @@ dump_dwarf (bfd *abfd)
|
||||||
else if (bfd_little_endian (abfd))
|
else if (bfd_little_endian (abfd))
|
||||||
byte_get = byte_get_little_endian;
|
byte_get = byte_get_little_endian;
|
||||||
else
|
else
|
||||||
abort ();
|
/* PR 17512: file: objdump-s-endless-loop.tekhex. */
|
||||||
|
{
|
||||||
|
warn (_("File %s does not contain any dwarf debug information\n"),
|
||||||
|
bfd_get_filename (abfd));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (bfd_get_arch (abfd))
|
switch (bfd_get_arch (abfd))
|
||||||
{
|
{
|
||||||
|
@ -2496,7 +2501,7 @@ print_section_stabs (bfd *abfd,
|
||||||
|
|
||||||
We start the index at -1 because there is a dummy symbol on
|
We start the index at -1 because there is a dummy symbol on
|
||||||
the front of stabs-in-{coff,elf} sections that supplies sizes. */
|
the front of stabs-in-{coff,elf} sections that supplies sizes. */
|
||||||
for (i = -1; stabp < stabs_end; stabp += STABSIZE, i++)
|
for (i = -1; stabp <= stabs_end - STABSIZE; stabp += STABSIZE, i++)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned long strx;
|
unsigned long strx;
|
||||||
|
@ -2534,10 +2539,13 @@ print_section_stabs (bfd *abfd,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
bfd_size_type amt = strx + file_string_table_offset;
|
||||||
|
|
||||||
/* Using the (possibly updated) string table offset, print the
|
/* Using the (possibly updated) string table offset, print the
|
||||||
string (if any) associated with this symbol. */
|
string (if any) associated with this symbol. */
|
||||||
if ((strx + file_string_table_offset) < stabstr_size)
|
if (amt < stabstr_size)
|
||||||
printf (" %s", &strtab[strx + file_string_table_offset]);
|
/* PR 17512: file: 079-79389-0.001:0.1. */
|
||||||
|
printf (" %.*s", (int)(stabstr_size - amt), strtab + amt);
|
||||||
else
|
else
|
||||||
printf (" *");
|
printf (" *");
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ struct coff_types
|
||||||
debug_type basic[T_MAX + 1];
|
debug_type basic[T_MAX + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
static debug_type *coff_get_slot (struct coff_types *, int);
|
static debug_type *coff_get_slot (struct coff_types *, long);
|
||||||
static debug_type parse_coff_type
|
static debug_type parse_coff_type
|
||||||
(bfd *, struct coff_symbols *, struct coff_types *, long, int,
|
(bfd *, struct coff_symbols *, struct coff_types *, long, int,
|
||||||
union internal_auxent *, bfd_boolean, void *);
|
union internal_auxent *, bfd_boolean, void *);
|
||||||
|
@ -104,12 +104,17 @@ static bfd_boolean external_coff_symbol_p (int sym_class);
|
||||||
/* Return the slot for a type. */
|
/* Return the slot for a type. */
|
||||||
|
|
||||||
static debug_type *
|
static debug_type *
|
||||||
coff_get_slot (struct coff_types *types, int indx)
|
coff_get_slot (struct coff_types *types, long indx)
|
||||||
{
|
{
|
||||||
struct coff_slots **pps;
|
struct coff_slots **pps;
|
||||||
|
|
||||||
pps = &types->slots;
|
pps = &types->slots;
|
||||||
|
|
||||||
|
/* PR 17512: file: 078-18333-0.001:0.1.
|
||||||
|
FIXME: The value of 1000 is a guess. Maybe a better heuristic is needed. */
|
||||||
|
if (indx / COFF_SLOTS > 1000)
|
||||||
|
fatal (_("Excessively large slot index: %lx"), indx);
|
||||||
|
|
||||||
while (indx >= COFF_SLOTS)
|
while (indx >= COFF_SLOTS)
|
||||||
{
|
{
|
||||||
if (*pps == NULL)
|
if (*pps == NULL)
|
||||||
|
|
|
@ -139,7 +139,7 @@ read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
|
||||||
}
|
}
|
||||||
|
|
||||||
strsize = bfd_section_size (abfd, strsec);
|
strsize = bfd_section_size (abfd, strsec);
|
||||||
strings = (bfd_byte *) xmalloc (strsize);
|
strings = (bfd_byte *) xmalloc (strsize + 1);
|
||||||
if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize))
|
if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize))
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s: %s: %s\n",
|
fprintf (stderr, "%s: %s: %s\n",
|
||||||
|
@ -147,7 +147,8 @@ read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
|
||||||
bfd_errmsg (bfd_get_error ()));
|
bfd_errmsg (bfd_get_error ()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
/* Zero terminate the strings table, just in case. */
|
||||||
|
strings [strsize] = 0;
|
||||||
if (shandle == NULL)
|
if (shandle == NULL)
|
||||||
{
|
{
|
||||||
shandle = start_stab (dhandle, abfd, TRUE, syms, symcount);
|
shandle = start_stab (dhandle, abfd, TRUE, syms, symcount);
|
||||||
|
@ -159,7 +160,8 @@ read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
|
||||||
|
|
||||||
stroff = 0;
|
stroff = 0;
|
||||||
next_stroff = 0;
|
next_stroff = 0;
|
||||||
for (stab = stabs; stab < stabs + stabsize; stab += 12)
|
/* PR 17512: file: 078-60391-0.001:0.1. */
|
||||||
|
for (stab = stabs; stab <= (stabs + stabsize) - 12; stab += 12)
|
||||||
{
|
{
|
||||||
unsigned int strx;
|
unsigned int strx;
|
||||||
int type;
|
int type;
|
||||||
|
@ -184,33 +186,43 @@ read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
size_t len;
|
||||||
char *f, *s;
|
char *f, *s;
|
||||||
|
|
||||||
f = NULL;
|
if (stroff + strx >= strsize)
|
||||||
|
|
||||||
if (stroff + strx > strsize)
|
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s: %s: stab entry %ld is corrupt, strx = 0x%x, type = %d\n",
|
fprintf (stderr, _("%s: %s: stab entry %ld is corrupt, strx = 0x%x, type = %d\n"),
|
||||||
bfd_get_filename (abfd), names[i].secname,
|
bfd_get_filename (abfd), names[i].secname,
|
||||||
(long) (stab - stabs) / 12, strx, type);
|
(long) (stab - stabs) / 12, strx, type);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = (char *) strings + stroff + strx;
|
s = (char *) strings + stroff + strx;
|
||||||
|
f = NULL;
|
||||||
|
|
||||||
while (s[strlen (s) - 1] == '\\'
|
/* PR 17512: file: 002-87578-0.001:0.1.
|
||||||
|
It is possible to craft a file where, without the 'strlen (s) > 0',
|
||||||
|
an attempt to read the byte before 'strings' would occur. */
|
||||||
|
while ((len = strlen (s)) > 0
|
||||||
|
&& s[len - 1] == '\\'
|
||||||
&& stab + 12 < stabs + stabsize)
|
&& stab + 12 < stabs + stabsize)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
stab += 12;
|
stab += 12;
|
||||||
p = s + strlen (s) - 1;
|
p = s + len - 1;
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
s = concat (s,
|
strx = stroff + bfd_get_32 (abfd, stab);
|
||||||
((char *) strings
|
if (strx >= strsize)
|
||||||
+ stroff
|
{
|
||||||
+ bfd_get_32 (abfd, stab)),
|
fprintf (stderr, _("%s: %s: stab entry %ld is corrupt\n"),
|
||||||
(const char *) NULL);
|
bfd_get_filename (abfd), names[i].secname,
|
||||||
|
(long) (stab - stabs) / 12);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s = concat (s, (char *) strings + strx,
|
||||||
|
(const char *) NULL);
|
||||||
|
|
||||||
/* We have to restore the backslash, because, if
|
/* We have to restore the backslash, because, if
|
||||||
the linker is hashing stabs strings, we may
|
the linker is hashing stabs strings, we may
|
||||||
|
|
|
@ -836,8 +836,6 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
|
||||||
|
|
||||||
case 'G':
|
case 'G':
|
||||||
{
|
{
|
||||||
char leading;
|
|
||||||
long c;
|
|
||||||
asymbol **ps;
|
asymbol **ps;
|
||||||
|
|
||||||
/* A global symbol. The value must be extracted from the
|
/* A global symbol. The value must be extracted from the
|
||||||
|
@ -846,19 +844,27 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
|
||||||
(debug_type **) NULL);
|
(debug_type **) NULL);
|
||||||
if (dtype == DEBUG_TYPE_NULL)
|
if (dtype == DEBUG_TYPE_NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
leading = bfd_get_symbol_leading_char (info->abfd);
|
if (name != NULL)
|
||||||
for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps)
|
|
||||||
{
|
{
|
||||||
const char *n;
|
char leading;
|
||||||
|
long c;
|
||||||
|
|
||||||
n = bfd_asymbol_name (*ps);
|
leading = bfd_get_symbol_leading_char (info->abfd);
|
||||||
if (leading != '\0' && *n == leading)
|
for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps)
|
||||||
++n;
|
{
|
||||||
if (*n == *name && strcmp (n, name) == 0)
|
const char *n;
|
||||||
break;
|
|
||||||
|
n = bfd_asymbol_name (*ps);
|
||||||
|
if (leading != '\0' && *n == leading)
|
||||||
|
++n;
|
||||||
|
if (*n == *name && strcmp (n, name) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c > 0)
|
||||||
|
value = bfd_asymbol_value (*ps);
|
||||||
}
|
}
|
||||||
if (c > 0)
|
|
||||||
value = bfd_asymbol_value (*ps);
|
|
||||||
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
|
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
|
||||||
value))
|
value))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue