From 4b0e8a5f80441fad8eddaf68e7af70bd6991aa37 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 11 Aug 2015 11:57:09 +0100 Subject: Fix memory access problems discovered when running some binary tools on corrupt files. PR binutils/18758 * elf.c (_bfd_elf_setup_sections): Add checks for corrupt section group information. * peicode.h (pe_ILF_make_a_section): Ensure alignment of the used_by_bfd pointer. (pe_ILF_build_a_bfd): Ensure alignment of vars.data pointer. --- bfd/ChangeLog | 9 +++++++++ bfd/elf.c | 17 +++++++++++++++-- bfd/peicode.h | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 91d41d3..b3b4239 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2015-08-11 Nick Clifton + + PR binutils/18758 + * elf.c (_bfd_elf_setup_sections): Add checks for corrupt section + group information. + * peicode.h (pe_ILF_make_a_section): Ensure alignment of the + used_by_bfd pointer. + (pe_ILF_build_a_bfd): Ensure alignment of vars.data pointer. + 2015-08-11 H.J. Lu * elf.c (_bfd_elf_copy_private_bfd_data): Fix a typo. diff --git a/bfd/elf.c b/bfd/elf.c index 15de37b..7ae2e34 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -817,9 +817,22 @@ _bfd_elf_setup_sections (bfd *abfd) for (i = 0; i < num_group; i++) { Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i]; - Elf_Internal_Group *idx = (Elf_Internal_Group *) shdr->contents; - unsigned int n_elt = shdr->sh_size / 4; + Elf_Internal_Group *idx; + unsigned int n_elt; + /* PR binutils/18758: Beware of corrupt binaries with invalid group data. */ + if (shdr == NULL || shdr->bfd_section == NULL || shdr->contents == NULL) + { + (*_bfd_error_handler) + (_("%B: section group entry number %u is corrupt"), + abfd, i); + result = FALSE; + continue; + } + + idx = (Elf_Internal_Group *) shdr->contents; + n_elt = shdr->sh_size / 4; + while (--n_elt != 0) if ((++idx)->shdr->bfd_section) elf_sec_group (idx->shdr->bfd_section) = shdr->bfd_section; diff --git a/bfd/peicode.h b/bfd/peicode.h index 06bcaa9..668e742 100644 --- a/bfd/peicode.h +++ b/bfd/peicode.h @@ -631,6 +631,20 @@ pe_ILF_make_a_section (pe_ILF_vars * vars, if (size & 1) vars->data --; +# if (GCC_VERSION >= 3000) + /* PR 18758: See note in pe_ILF_buid_a_bfd. We must make sure that we + preserve host alignment requirements. We test 'size' rather than + vars.data as we cannot perform binary arithmetic on pointers. We assume + that vars.data was sufficiently aligned upon entry to this function. + The BFD_ASSERTs in this functions will warn us if we run out of room, + but we should already have enough padding built in to ILF_DATA_SIZE. */ + { + unsigned int alignment = __alignof__ (struct coff_section_tdata); + + if (size & (alignment - 1)) + vars->data += alignment - (size & (alignment - 1)); + } +#endif /* Create a coff_section_tdata structure for our use. */ sec->used_by_bfd = (struct coff_section_tdata *) vars->data; vars->data += sizeof (struct coff_section_tdata); @@ -836,6 +850,24 @@ pe_ILF_build_a_bfd (bfd * abfd, /* The remaining space in bim->buffer is used by the pe_ILF_make_a_section() function. */ +# if (GCC_VERSION >= 3000) + /* PR 18758: Make sure that the data area is sufficiently aligned for + pointers on the host. __alignof__ is a gcc extension, hence the test + above. For other compilers we will have to assume that the alignment is + unimportant, or else extra code can be added here and in + pe_ILF_make_a_section. + + Note - we cannot test 'ptr' directly as it is illegal to perform binary + arithmetic on pointers, but we know that the strings section is the only + one that might end on an unaligned boundary. */ + { + unsigned int alignment = __alignof__ (char *); + + if (SIZEOF_ILF_STRINGS & (alignment - 1)) + ptr += alignment - (SIZEOF_ILF_STRINGS & (alignment - 1)); + } +#endif + vars.data = ptr; vars.abfd = abfd; vars.sec_index = 0; -- cgit v1.1