Fix memory access problems discovered when running some binary tools on corrupt files.
authorNick Clifton <nickc@redhat.com>
Tue, 11 Aug 2015 10:57:09 +0000 (11:57 +0100)
committerNick Clifton <nickc@redhat.com>
Tue, 11 Aug 2015 10:57:09 +0000 (11:57 +0100)
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
bfd/elf.c
bfd/peicode.h

index 91d41d353d33193a34e8983ba0068c979e216f6a..b3b4239dc3596d25ba4c6f37735e2ff5e2924c62 100644 (file)
@@ -1,3 +1,12 @@
+2015-08-11  Nick Clifton  <nickc@redhat.com>
+
+       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  <hongjiu.lu@intel.com>
 
        * elf.c (_bfd_elf_copy_private_bfd_data): Fix a typo.
index 15de37b5fd084073a68c5a012027459f410989f6..7ae2e342525e3c59da575893ab42ba590ea86fc6 100644 (file)
--- 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;
index 06bcaa9272f7cd436978887067c3056e531ac903..668e7429db9ddaff143a95f5463c92be5de51ea8 100644 (file)
@@ -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;