From 513ea82edf8533e3483073561c06be97de035c83 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 14 Aug 2014 15:53:19 +0930 Subject: [PATCH] Fix for objdump segfault on broken PE executable * peXXigen.c (pe_print_reloc): Protect against access past end of .reloc section. --- bfd/ChangeLog | 5 +++++ bfd/peXXigen.c | 37 ++++++++++++++++++++----------------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 4ee7c3d2d7a..a23a2c3b8f3 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2014-08-14 Alan Modra + + * peXXigen.c (pe_print_reloc): Protect against access past end + of .reloc section. + 2014-08-14 Alan Modra PR 16563 diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c index 3808d39f812..2fb631c5a76 100644 --- a/bfd/peXXigen.c +++ b/bfd/peXXigen.c @@ -2092,8 +2092,7 @@ pe_print_reloc (bfd * abfd, void * vfile) FILE *file = (FILE *) vfile; bfd_byte *data = 0; asection *section = bfd_get_section_by_name (abfd, ".reloc"); - bfd_size_type i; - bfd_size_type start, stop; + bfd_byte *p, *end; if (section == NULL || section->size == 0 || !(section->flags & SEC_HAS_CONTENTS)) return TRUE; @@ -2108,20 +2107,20 @@ pe_print_reloc (bfd * abfd, void * vfile) return FALSE; } - start = 0; - - stop = section->size; - - for (i = start; i < stop;) + p = data; + end = data + section->size; + while (p + 8 <= end) { int j; bfd_vma virtual_address; long number, size; + bfd_byte *chunk_end; /* The .reloc section is a sequence of blocks, with a header consisting of two 32 bit quantities, followed by a number of 16 bit entries. */ - virtual_address = bfd_get_32 (abfd, data+i); - size = bfd_get_32 (abfd, data+i+4); + virtual_address = bfd_get_32 (abfd, p); + size = bfd_get_32 (abfd, p + 4); + p += 8; number = (size - 8) / 2; if (size == 0) @@ -2131,9 +2130,13 @@ pe_print_reloc (bfd * abfd, void * vfile) _("\nVirtual Address: %08lx Chunk size %ld (0x%lx) Number of fixups %ld\n"), (unsigned long) virtual_address, size, (unsigned long) size, number); - for (j = 0; j < number; ++j) + chunk_end = p + size; + if (chunk_end > end) + chunk_end = end; + j = 0; + while (p + 2 <= chunk_end) { - unsigned short e = bfd_get_16 (abfd, data + i + 8 + j * 2); + unsigned short e = bfd_get_16 (abfd, p); unsigned int t = (e & 0xF000) >> 12; int off = e & 0x0FFF; @@ -2144,20 +2147,20 @@ pe_print_reloc (bfd * abfd, void * vfile) _("\treloc %4d offset %4x [%4lx] %s"), j, off, (unsigned long) (off + virtual_address), tbl[t]); + p += 2; + j++; + /* HIGHADJ takes an argument, - the next record *is* the low 16 bits of addend. */ - if (t == IMAGE_REL_BASED_HIGHADJ) + if (t == IMAGE_REL_BASED_HIGHADJ && p + 2 <= chunk_end) { - fprintf (file, " (%4x)", - ((unsigned int) - bfd_get_16 (abfd, data + i + 8 + j * 2 + 2))); + fprintf (file, " (%4x)", (unsigned int) bfd_get_16 (abfd, p)); + p += 2; j++; } fprintf (file, "\n"); } - - i += size; } free (data);