Fixes illegal memory accesses triggereb by running a 32-bit binary version of objdump compiled on a 64-bit host.

PR binutils/17512
	* dwarf.c (display_debug_frames): Fix range checks to work on
	32-bit binaries complied on a 64-bit host.

	* peXXigen.c (rsrc_print_resource_entries): Add range check for
	addresses that wrap around the address space.
	(rsrc_parse_entry): Likewise.
This commit is contained in:
Nick Clifton
2015-02-06 11:12:02 +00:00
parent 77f4176143
commit 5929c344f9
4 changed files with 39 additions and 14 deletions

View File

@ -1,3 +1,10 @@
2015-02-06 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* peXXigen.c (rsrc_print_resource_entries): Add range check for
addresses that wrap around the address space.
(rsrc_parse_entry): Likewise.
2015-02-03 H.J. Lu <hongjiu.lu@intel.com> 2015-02-03 H.J. Lu <hongjiu.lu@intel.com>
PR ld/12365 PR ld/12365

View File

@ -2302,6 +2302,7 @@ rsrc_print_resource_entries (FILE * file,
bfd_vma rva_bias) bfd_vma rva_bias)
{ {
unsigned long entry, addr, size; unsigned long entry, addr, size;
bfd_byte * leaf;
if (data + 8 >= regions->section_end) if (data + 8 >= regions->section_end)
return regions->section_end + 1; return regions->section_end + 1;
@ -2382,18 +2383,21 @@ rsrc_print_resource_entries (FILE * file,
regions, rva_bias); regions, rva_bias);
} }
if (regions->section_start + entry + 16 >= regions->section_end) leaf = regions->section_start + entry;
if (leaf + 16 >= regions->section_end
/* PR 17512: file: 055dff7e. */
|| leaf < regions->section_start)
return regions->section_end + 1; return regions->section_end + 1;
fprintf (file, _("%03x %*.s Leaf: Addr: %#08lx, Size: %#08lx, Codepage: %d\n"), fprintf (file, _("%03x %*.s Leaf: Addr: %#08lx, Size: %#08lx, Codepage: %d\n"),
(int) (entry), (int) (entry), indent, " ",
indent, " ", addr = (long) bfd_get_32 (abfd, leaf),
addr = (long) bfd_get_32 (abfd, regions->section_start + entry), size = (long) bfd_get_32 (abfd, leaf + 4),
size = (long) bfd_get_32 (abfd, regions->section_start + entry + 4), (int) bfd_get_32 (abfd, leaf + 8));
(int) bfd_get_32 (abfd, regions->section_start + entry + 8));
/* Check that the reserved entry is 0. */ /* Check that the reserved entry is 0. */
if (bfd_get_32 (abfd, regions->section_start + entry + 12) != 0 if (bfd_get_32 (abfd, leaf + 12) != 0
/* And that the data address/size is valid too. */ /* And that the data address/size is valid too. */
|| (regions->section_start + (addr - rva_bias) + size > regions->section_end)) || (regions->section_start + (addr - rva_bias) + size > regions->section_end))
return regions->section_end + 1; return regions->section_end + 1;
@ -3264,9 +3268,14 @@ rsrc_parse_entry (bfd * abfd,
if (entry->value.leaf == NULL) if (entry->value.leaf == NULL)
return dataend; return dataend;
addr = bfd_get_32 (abfd, datastart + val); data = datastart + val;
size = entry->value.leaf->size = bfd_get_32 (abfd, datastart + val + 4); if (data < datastart || data >= dataend)
entry->value.leaf->codepage = bfd_get_32 (abfd, datastart + val + 8); return dataend;
addr = bfd_get_32 (abfd, data);
size = entry->value.leaf->size = bfd_get_32 (abfd, data + 4);
entry->value.leaf->codepage = bfd_get_32 (abfd, data + 8);
/* FIXME: We assume that the reserved field (data + 12) is OK. */
entry->value.leaf->data = bfd_malloc (size); entry->value.leaf->data = bfd_malloc (size);
if (entry->value.leaf->data == NULL) if (entry->value.leaf->data == NULL)

View File

@ -1,3 +1,9 @@
2015-02-06 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* dwarf.c (display_debug_frames): Fix range checks to work on
32-bit binaries complied on a 64-bit host.
2015-02-05 Alan Modra <amodra@gmail.com> 2015-02-05 Alan Modra <amodra@gmail.com>
PR binutils/17926 PR binutils/17926

View File

@ -5949,6 +5949,7 @@ display_debug_frames (struct dwarf_section *section,
{ {
unsigned int reg, op, opa; unsigned int reg, op, opa;
unsigned long temp; unsigned long temp;
unsigned char * new_start;
op = *start++; op = *start++;
opa = op & 0x3f; opa = op & 0x3f;
@ -6019,26 +6020,28 @@ display_debug_frames (struct dwarf_section *section,
break; break;
case DW_CFA_def_cfa_expression: case DW_CFA_def_cfa_expression:
temp = LEB (); temp = LEB ();
if (start + temp < start) new_start = start + temp;
if (new_start < start)
{ {
warn (_("Corrupt CFA_def expression value: %lu\n"), temp); warn (_("Corrupt CFA_def expression value: %lu\n"), temp);
start = block_end; start = block_end;
} }
else else
start += temp; start = new_start;
break; break;
case DW_CFA_expression: case DW_CFA_expression:
case DW_CFA_val_expression: case DW_CFA_val_expression:
reg = LEB (); reg = LEB ();
temp = LEB (); temp = LEB ();
if (start + temp < start) new_start = start + temp;
if (new_start < start)
{ {
/* PR 17512: file:306-192417-0.005. */ /* PR 17512: file:306-192417-0.005. */
warn (_("Corrupt CFA expression value: %lu\n"), temp); warn (_("Corrupt CFA expression value: %lu\n"), temp);
start = block_end; start = block_end;
} }
else else
start += temp; start = new_start;
if (frame_need_space (fc, reg) >= 0) if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined; fc->col_type[reg] = DW_CFA_undefined;
break; break;