Fix illegal memory access parsing a corrupt ELF file.
authorNick Clifton <nickc@redhat.com>
Thu, 14 Mar 2019 14:45:32 +0000 (14:45 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 14 Mar 2019 14:45:32 +0000 (14:45 +0000)
PR 24332
* elflink.c (elf_link_add_object_symbols): Add new local variable
extversym_end.  Initialise it to point to the end of the version
symbol table, if present.  Check it when initialising and updating
the ever pointer.

bfd/ChangeLog
bfd/elflink.c

index 540f7373cabd7fb1cea6cc42236ffc12153dd387..447eb707c877399943c8913826c88979dbf614dc 100644 (file)
@@ -1,3 +1,11 @@
+2019-03-14  Nick Clifton  <nickc@redhat.com>
+
+       PR 24332
+       * elflink.c (elf_link_add_object_symbols): Add new local variable
+       extversym_end.  Initialise it to point to the end of the version
+       symbol table, if present.  Check it when initialising and updating
+       the ever pointer.
+
 2019-03-13  Sudakshina Das  <sudi.das@arm.com>
 
        * elfnn-aarch64.c (PLT_PAC_ENTRY_SIZE, PLT_PAC_SMALL_ENTRY_SIZE): New.
index e50c0e4b38e932bc8240485269c4f59572e1a896..3ac58daafda812d1db60999691e47217c2c15621 100644 (file)
@@ -3872,6 +3872,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   struct elf_link_hash_entry **sym_hash;
   bfd_boolean dynamic;
   Elf_External_Versym *extversym = NULL;
+  Elf_External_Versym *extversym_end = NULL;
   Elf_External_Versym *ever;
   struct elf_link_hash_entry *weaks;
   struct elf_link_hash_entry **nondeflt_vers = NULL;
@@ -4297,13 +4298,14 @@ error_free_dyn:
          Elf_Internal_Shdr *versymhdr;
 
          versymhdr = &elf_tdata (abfd)->dynversym_hdr;
-         extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
+         amt = versymhdr->sh_size;
+         extversym = (Elf_External_Versym *) bfd_malloc (amt);
          if (extversym == NULL)
            goto error_free_sym;
-         amt = versymhdr->sh_size;
          if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0
              || bfd_bread (extversym, amt, abfd) != amt)
            goto error_free_vers;
+         extversym_end = extversym + (amt / sizeof (* extversym));
        }
     }
 
@@ -4378,7 +4380,20 @@ error_free_dyn:
     }
 
   weaks = NULL;
-  ever = extversym != NULL ? extversym + extsymoff : NULL;
+  if (extversym == NULL)
+    ever = NULL;
+  else if (extversym + extsymoff < extversym_end)
+    ever = extversym + extsymoff;
+  else
+    {
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: invalid version offset %lx (max %lx)"),
+                         abfd, (long) extsymoff,
+                         (long) (extversym_end - extversym) / sizeof (* extversym));
+      bfd_set_error (bfd_error_bad_value);
+      goto error_free_vers;
+    }
+
   for (isym = isymbuf, isymend = isymbuf + extsymcount;
        isym < isymend;
        isym++, sym_hash++, ever = (ever != NULL ? ever + 1 : NULL))
@@ -4562,6 +4577,14 @@ error_free_dyn:
              else
                iver.vs_vers = 0;
            }
+         else if (ever >= extversym_end)
+           {
+             /* xgettext:c-format */
+             _bfd_error_handler (_("%pB: not enough version information"),
+                                 abfd);
+             bfd_set_error (bfd_error_bad_value);
+             goto error_free_vers;
+           }
          else
            _bfd_elf_swap_versym_in (abfd, ever, &iver);
 
This page took 0.031674 seconds and 4 git commands to generate.