goto error_return;
 
   /* Dynamic string table must be valid until ABFD is closed.  */
-  strbuf = (char *) _bfd_alloc_and_read (abfd, dt_strsz, dt_strsz);
+  strbuf = (char *) _bfd_alloc_and_read (abfd, dt_strsz + 1, dt_strsz);
   if (strbuf == NULL)
     goto error_return;
+  /* Since this is a string table, make sure that it is terminated.  */
+  strbuf[dt_strsz] = 0;
 
   /* Get the real symbol count from DT_HASH or DT_GNU_HASH.  Prefer
      DT_HASH since it is simpler than DT_GNU_HASH.  */
 
  empty_gnu_hash:
   elf_tdata (abfd)->dt_strtab = strbuf;
+  elf_tdata (abfd)->dt_strsz = dt_strsz;
   elf_tdata (abfd)->dt_symtab = isymbuf;
   elf_tdata (abfd)->dt_symtab_count = symcount;
   elf_tdata (abfd)->dt_versym = versym;
 _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
 {
   bfd_byte *contents = NULL;
+  bool free_contents = false;
   unsigned int freeidx = 0;
   size_t amt;
 
          if (contents == NULL)
            goto error_return_verref;
 
+         free_contents = true;
          verneed_size = hdr->sh_size;
          verneed_count = hdr->sh_info;
        }
          iverneed->vn_bfd = abfd;
 
          if (elf_use_dt_symtab_p (abfd))
-           iverneed->vn_filename
-             = elf_tdata (abfd)->dt_strtab + iverneed->vn_file;
+           {
+             if (iverneed->vn_file < elf_tdata (abfd)->dt_strsz)
+               iverneed->vn_filename
+                 = elf_tdata (abfd)->dt_strtab + iverneed->vn_file;
+             else
+               iverneed->vn_filename = NULL;
+           }   
          else
            iverneed->vn_filename
              = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
              _bfd_elf_swap_vernaux_in (abfd, evernaux, ivernaux);
 
              if (elf_use_dt_symtab_p (abfd))
-               ivernaux->vna_nodename
-                 = elf_tdata (abfd)->dt_strtab + ivernaux->vna_name;
+               {
+                 if (ivernaux->vna_name < elf_tdata (abfd)->dt_strsz)
+                   ivernaux->vna_nodename
+                     = elf_tdata (abfd)->dt_strtab + ivernaux->vna_name;
+                 else
+                   ivernaux->vna_nodename = NULL;
+               }
              else
                ivernaux->vna_nodename
                  = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
              _bfd_elf_swap_verdaux_in (abfd, everdaux, iverdaux);
 
              if (elf_use_dt_symtab_p (abfd))
-               iverdaux->vda_nodename
-                 = elf_tdata (abfd)->dt_strtab + iverdaux->vda_name;
+               {
+                 if (iverdaux->vda_name < elf_tdata (abfd)->dt_strsz)
+                   iverdaux->vda_nodename
+                     = elf_tdata (abfd)->dt_strtab + iverdaux->vda_name;
+                 else
+                   iverdaux->vda_nodename = NULL;
+               }
              else
                iverdaux->vda_nodename
                  = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
   return true;
 
  error_return:
-  free (contents);
+  if (free_contents)
+    free (contents);
   return false;
 }
 \f