Fixes for invalid memory accesses triggered by running readelf on fuzzed binaries.
PR binutils/17531 * dwarf.c (display_debug_pubnames_worker): Work around compiler bug checking address ranges. (display_debug_frames): Likewise. (display_gdb_index): Likewise. (process_cu_tu_index): Add range check on the ncols value.
This commit is contained in:
parent
439b7f41b5
commit
362beea4b4
2 changed files with 38 additions and 15 deletions
|
@ -1,3 +1,12 @@
|
||||||
|
2015-02-11 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
PR binutils/17531
|
||||||
|
* dwarf.c (display_debug_pubnames_worker): Work around compiler
|
||||||
|
bug checking address ranges.
|
||||||
|
(display_debug_frames): Likewise.
|
||||||
|
(display_gdb_index): Likewise.
|
||||||
|
(process_cu_tu_index): Add range check on the ncols value.
|
||||||
|
|
||||||
2015-02-10 Nick Clifton <nickc@redhat.com>
|
2015-02-10 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
PR binutils/17512
|
PR binutils/17512
|
||||||
|
|
|
@ -3725,6 +3725,7 @@ display_debug_pubnames_worker (struct dwarf_section *section,
|
||||||
while (start < end)
|
while (start < end)
|
||||||
{
|
{
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
|
unsigned char *adr;
|
||||||
dwarf_vma offset;
|
dwarf_vma offset;
|
||||||
unsigned int offset_size, initial_length_size;
|
unsigned int offset_size, initial_length_size;
|
||||||
|
|
||||||
|
@ -3754,17 +3755,18 @@ display_debug_pubnames_worker (struct dwarf_section *section,
|
||||||
|
|
||||||
SAFE_BYTE_GET_AND_INC (names.pn_size, data, offset_size, end);
|
SAFE_BYTE_GET_AND_INC (names.pn_size, data, offset_size, end);
|
||||||
|
|
||||||
|
adr = start + names.pn_length + initial_length_size;
|
||||||
/* PR 17531: file: 7615b6b2. */
|
/* PR 17531: file: 7615b6b2. */
|
||||||
if ((dwarf_signed_vma) names.pn_length < 0
|
if ((dwarf_signed_vma) names.pn_length < 0
|
||||||
/* PR 17531: file: a5dbeaa7. */
|
/* PR 17531: file: a5dbeaa7. */
|
||||||
|| start + names.pn_length + initial_length_size < start)
|
|| adr < start)
|
||||||
{
|
{
|
||||||
warn (_("Negative length for public name: 0x%lx\n"), (long) names.pn_length);
|
warn (_("Negative length for public name: 0x%lx\n"), (long) names.pn_length);
|
||||||
start = end;
|
start = end;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
start += names.pn_length + initial_length_size;
|
start = adr;
|
||||||
|
|
||||||
printf (_(" Length: %ld\n"),
|
printf (_(" Length: %ld\n"),
|
||||||
(long) names.pn_length);
|
(long) names.pn_length);
|
||||||
printf (_(" Version: %d\n"),
|
printf (_(" Version: %d\n"),
|
||||||
|
@ -6111,6 +6113,7 @@ display_debug_frames (struct dwarf_section *section,
|
||||||
|
|
||||||
while (start < block_end)
|
while (start < block_end)
|
||||||
{
|
{
|
||||||
|
unsigned char * tmp;
|
||||||
unsigned op, opa;
|
unsigned op, opa;
|
||||||
unsigned long ul, reg, roffs;
|
unsigned long ul, reg, roffs;
|
||||||
long l;
|
long l;
|
||||||
|
@ -6412,7 +6415,8 @@ display_debug_frames (struct dwarf_section *section,
|
||||||
reg_prefix = bad_reg;
|
reg_prefix = bad_reg;
|
||||||
/* PR 17512: file: 069-133014-0.006. */
|
/* PR 17512: file: 069-133014-0.006. */
|
||||||
/* PR 17512: file: 98c02eb4. */
|
/* PR 17512: file: 98c02eb4. */
|
||||||
if (start >= block_end || start + ul > block_end || start + ul < start)
|
tmp = start + ul;
|
||||||
|
if (start >= block_end || tmp > block_end || tmp < start)
|
||||||
{
|
{
|
||||||
printf (_(" DW_CFA_expression: <corrupt len %lu>\n"), ul);
|
printf (_(" DW_CFA_expression: <corrupt len %lu>\n"), ul);
|
||||||
break;
|
break;
|
||||||
|
@ -6427,7 +6431,7 @@ display_debug_frames (struct dwarf_section *section,
|
||||||
}
|
}
|
||||||
if (*reg_prefix == '\0')
|
if (*reg_prefix == '\0')
|
||||||
fc->col_type[reg] = DW_CFA_expression;
|
fc->col_type[reg] = DW_CFA_expression;
|
||||||
start += ul;
|
start = tmp;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_val_expression:
|
case DW_CFA_val_expression:
|
||||||
|
@ -6435,7 +6439,8 @@ display_debug_frames (struct dwarf_section *section,
|
||||||
ul = LEB ();
|
ul = LEB ();
|
||||||
if (reg >= (unsigned int) fc->ncols)
|
if (reg >= (unsigned int) fc->ncols)
|
||||||
reg_prefix = bad_reg;
|
reg_prefix = bad_reg;
|
||||||
if (start >= block_end || start + ul > block_end || start + ul < start)
|
tmp = start + ul;
|
||||||
|
if (start >= block_end || tmp > block_end || tmp < start)
|
||||||
{
|
{
|
||||||
printf (" DW_CFA_val_expression: <corrupt len %lu>\n", ul);
|
printf (" DW_CFA_val_expression: <corrupt len %lu>\n", ul);
|
||||||
break;
|
break;
|
||||||
|
@ -6450,7 +6455,7 @@ display_debug_frames (struct dwarf_section *section,
|
||||||
}
|
}
|
||||||
if (*reg_prefix == '\0')
|
if (*reg_prefix == '\0')
|
||||||
fc->col_type[reg] = DW_CFA_val_expression;
|
fc->col_type[reg] = DW_CFA_val_expression;
|
||||||
start += ul;
|
start = tmp;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_CFA_offset_extended_sf:
|
case DW_CFA_offset_extended_sf:
|
||||||
|
@ -6729,10 +6734,11 @@ display_gdb_index (struct dwarf_section *section,
|
||||||
|| cu_vector_offset != 0)
|
|| cu_vector_offset != 0)
|
||||||
{
|
{
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
|
unsigned char * adr;
|
||||||
|
|
||||||
|
adr = constant_pool + name_offset;
|
||||||
/* PR 17531: file: 5b7b07ad. */
|
/* PR 17531: file: 5b7b07ad. */
|
||||||
if (constant_pool + name_offset < constant_pool
|
if (adr < constant_pool || adr >= section->start + section->size)
|
||||||
|| constant_pool + name_offset >= section->start + section->size)
|
|
||||||
{
|
{
|
||||||
printf (_("[%3u] <corrupt offset: %x>"), i, name_offset);
|
printf (_("[%3u] <corrupt offset: %x>"), i, name_offset);
|
||||||
warn (_("Corrupt name offset of 0x%x found for symbol table slot %d\n"),
|
warn (_("Corrupt name offset of 0x%x found for symbol table slot %d\n"),
|
||||||
|
@ -6743,8 +6749,8 @@ display_gdb_index (struct dwarf_section *section,
|
||||||
(int) (section->size - (constant_pool_offset + name_offset)),
|
(int) (section->size - (constant_pool_offset + name_offset)),
|
||||||
constant_pool + name_offset);
|
constant_pool + name_offset);
|
||||||
|
|
||||||
if (constant_pool + cu_vector_offset < constant_pool
|
adr = constant_pool + cu_vector_offset;
|
||||||
|| constant_pool + cu_vector_offset >= section->start + section->size - 3)
|
if (adr < constant_pool || adr >= section->start + section->size - 3)
|
||||||
{
|
{
|
||||||
printf (_("<invalid CU vector offset: %x>\n"), cu_vector_offset);
|
printf (_("<invalid CU vector offset: %x>\n"), cu_vector_offset);
|
||||||
warn (_("Corrupt CU vector offset of 0x%x found for symbol table slot %d\n"),
|
warn (_("Corrupt CU vector offset of 0x%x found for symbol table slot %d\n"),
|
||||||
|
@ -6752,12 +6758,12 @@ display_gdb_index (struct dwarf_section *section,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_cus = byte_get_little_endian (constant_pool + cu_vector_offset, 4);
|
num_cus = byte_get_little_endian (adr, 4);
|
||||||
|
|
||||||
|
adr = constant_pool + cu_vector_offset + 4 + num_cus * 4;
|
||||||
if (num_cus * 4 < num_cus
|
if (num_cus * 4 < num_cus
|
||||||
|| constant_pool + cu_vector_offset + 4 + num_cus * 4
|
|| adr >= section->start + section->size
|
||||||
>= section->start + section->size
|
|| adr < constant_pool)
|
||||||
|| (constant_pool + cu_vector_offset + 4 + num_cus * 4) < constant_pool)
|
|
||||||
{
|
{
|
||||||
printf ("<invalid number of CUs: %d>\n", num_cus);
|
printf ("<invalid number of CUs: %d>\n", num_cus);
|
||||||
warn (_("Invalid number of CUs (0x%x) for symbol table slot %d\n"),
|
warn (_("Invalid number of CUs (0x%x) for symbol table slot %d\n"),
|
||||||
|
@ -7011,6 +7017,14 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
|
||||||
|
|
||||||
is_tu_index = strcmp (section->name, ".debug_tu_index") == 0;
|
is_tu_index = strcmp (section->name, ".debug_tu_index") == 0;
|
||||||
|
|
||||||
|
/* PR 17531: file: 0dd159bf.
|
||||||
|
Check for wraparound with an overlarge ncols value. */
|
||||||
|
if ((unsigned int) ((poffsets - ppool) / 4) != ncols)
|
||||||
|
{
|
||||||
|
warn (_("Overlarge number of columns: %x\n"), ncols);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (pend > limit)
|
if (pend > limit)
|
||||||
{
|
{
|
||||||
warn (_("Section %s too small for offset and size tables\n"),
|
warn (_("Section %s too small for offset and size tables\n"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue