PR23994, libbfd integer overflow
authorAlan Modra <amodra@gmail.com>
Sun, 16 Dec 2018 12:32:50 +0000 (23:02 +1030)
committerAlan Modra <amodra@gmail.com>
Mon, 17 Dec 2018 02:19:38 +0000 (12:49 +1030)
PR 23994
* aoutx.h: Include limits.h.
(get_reloc_upper_bound): Detect long overflow and return a file
too big error if it occurs.
* elf.c: Include limits.h.
(_bfd_elf_get_symtab_upper_bound): Detect long overflow and return
a file too big error if it occurs.
(_bfd_elf_get_dynamic_symtab_upper_bound): Likewise.
(_bfd_elf_get_dynamic_reloc_upper_bound): Likewise.

bfd/ChangeLog
bfd/aoutx.h
bfd/elf.c

index 7ddcf7efa25db6cdcb38036dd3b54e30828c555a..9e5717e89fbe5d331a67eb95d20fabeba195e55a 100644 (file)
@@ -1,3 +1,15 @@
+2018-12-17  Alan Modra  <amodra@gmail.com>
+
+       PR 23994
+       * aoutx.h: Include limits.h.
+       (get_reloc_upper_bound): Detect long overflow and return a file
+       too big error if it occurs.
+       * elf.c: Include limits.h.
+       (_bfd_elf_get_symtab_upper_bound): Detect long overflow and return
+       a file too big error if it occurs.
+       (_bfd_elf_get_dynamic_symtab_upper_bound): Likewise.
+       (_bfd_elf_get_dynamic_reloc_upper_bound): Likewise.
+
 2018-12-14  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/23900
index 023843b0be42fa6ec4ade4f3a4111f437776fc63..78eaa9c5034f1e3a854e040c7575f2ba126177b6 100644 (file)
@@ -117,6 +117,7 @@ DESCRIPTION
 #define KEEPIT udata.i
 
 #include "sysdep.h"
+#include <limits.h>
 #include "bfd.h"
 #include "safe-ctype.h"
 #include "bfdlink.h"
@@ -2491,6 +2492,8 @@ NAME (aout, canonicalize_reloc) (bfd *abfd,
 long
 NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
 {
+  bfd_size_type count;
+
   if (bfd_get_format (abfd) != bfd_object)
     {
       bfd_set_error (bfd_error_invalid_operation);
@@ -2498,26 +2501,25 @@ NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
     }
 
   if (asect->flags & SEC_CONSTRUCTOR)
-    return sizeof (arelent *) * (asect->reloc_count + 1);
-
-  if (asect == obj_datasec (abfd))
-    return sizeof (arelent *)
-      * ((exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd))
-        + 1);
-
-  if (asect == obj_textsec (abfd))
-    return sizeof (arelent *)
-      * ((exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd))
-        + 1);
-
-  if (asect == obj_bsssec (abfd))
-    return sizeof (arelent *);
-
-  if (asect == obj_bsssec (abfd))
-    return 0;
+    count = asect->reloc_count;
+  else if (asect == obj_datasec (abfd))
+    count = exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd);
+  else if (asect == obj_textsec (abfd))
+    count = exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd);
+  else if (asect == obj_bsssec (abfd))
+    count = 0;
+  else
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return -1;
+    }
 
-  bfd_set_error (bfd_error_invalid_operation);
-  return -1;
+  if (count >= LONG_MAX / sizeof (arelent *))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return -1;
+    }
+  return (count + 1) * sizeof (arelent *);
 }
 \f
 long
index 688429b73e44efa3d3854c87165e7517925ddccc..b10dcd83c5506a53c580d6f66dfc61082de19268 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -35,6 +35,7 @@ SECTION
 /* For sparc64-cross-sparc32.  */
 #define _SYSCALL32
 #include "sysdep.h"
+#include <limits.h>
 #include "bfd.h"
 #include "bfdlink.h"
 #include "libbfd.h"
@@ -8215,11 +8216,16 @@ error_return:
 long
 _bfd_elf_get_symtab_upper_bound (bfd *abfd)
 {
-  long symcount;
+  bfd_size_type symcount;
   long symtab_size;
   Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->symtab_hdr;
 
   symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
+  if (symcount >= LONG_MAX / sizeof (asymbol *))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return -1;
+    }
   symtab_size = (symcount + 1) * (sizeof (asymbol *));
   if (symcount > 0)
     symtab_size -= sizeof (asymbol *);
@@ -8230,7 +8236,7 @@ _bfd_elf_get_symtab_upper_bound (bfd *abfd)
 long
 _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
 {
-  long symcount;
+  bfd_size_type symcount;
   long symtab_size;
   Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->dynsymtab_hdr;
 
@@ -8241,6 +8247,11 @@ _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
     }
 
   symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
+  if (symcount >= LONG_MAX / sizeof (asymbol *))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return -1;
+    }
   symtab_size = (symcount + 1) * (sizeof (asymbol *));
   if (symcount > 0)
     symtab_size -= sizeof (asymbol *);
@@ -8310,7 +8321,7 @@ _bfd_elf_canonicalize_dynamic_symtab (bfd *abfd,
 long
 _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
 {
-  long ret;
+  bfd_size_type count;
   asection *s;
 
   if (elf_dynsymtab (abfd) == 0)
@@ -8319,15 +8330,20 @@ _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
       return -1;
     }
 
-  ret = sizeof (arelent *);
+  count = 1;
   for (s = abfd->sections; s != NULL; s = s->next)
     if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
        && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
            || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
-      ret += ((s->size / elf_section_data (s)->this_hdr.sh_entsize)
-             * sizeof (arelent *));
-
-  return ret;
+      {
+       count += s->size / elf_section_data (s)->this_hdr.sh_entsize;
+       if (count > LONG_MAX / sizeof (arelent *))
+         {
+           bfd_set_error (bfd_error_file_too_big);
+           return -1;
+         }
+      }
+  return count * sizeof (arelent *);
 }
 
 /* Canonicalize the dynamic relocation entries.  Note that we return the