* readelf.c (cmalloc, xcmalloc, xcrealloc): New functions.
authorJakub Jelinek <jakub@redhat.com>
Tue, 14 Jun 2005 11:06:28 +0000 (11:06 +0000)
committerJakub Jelinek <jakub@redhat.com>
Tue, 14 Jun 2005 11:06:28 +0000 (11:06 +0000)
(get_data): Add nmemb argument.  Return NULL if nmemb * size
overflows.  If var == NULL, allocate one extra byte and
clear it.
(slurp_rela_relocs, slurp_rel_relocs, get_32bit_program_headers,
get_64bit_program_headers, get_program_headers,
get_32bit_section_headers, get_64bit_section_headers,
get_32bit_elf_symbols, get_64bit_elf_symbols, process_section_headers,
process_section_groups, process_relocs, slurp_ia64_unwind_table,
ia64_process_unwind, slurp_hppa_unwind_table, hppa_process_unwind,
get_32bit_dynamic_section, get_64bit_dynamic_section,
process_dynamic_section, process_version_sections, get_dynamic_data,
process_symbol_table, dump_section, load_debug_str, load_debug_loc,
load_debug_range, read_and_display_attr_value, process_debug_info,
get_debug_info, frame_need_space, display_debug_frames,
display_debug_section, process_mips_specific, process_gnu_liblist,
process_corefile_note_segment): Adjust get_data callers.  Use
cmalloc, xcmalloc and xcrealloc instead of {m,xm,xre}alloc where
passed size is a product of 2 numbers.

* readelf.c (print_mode): Fix comment typo.
(slurp_rela_relocs, slurp_rel_relocs): Fix memory leaks.
(dump_relocations): Fix a thinko in check for invalid st_name.
(process_program_headers): Don't crash if string_table is NULL.
(process_section_headers): Don't crash if e_shstrndx is invalid.
Ensure string_table_length is 0 if string_table == NULL.
Don't return just because string_table is NULL.
(process_section_groups): Don't crash if symtab's sh_link or
symbol's st_name is invalid.  Fix a memory leak.  Fix check for
invalid section number entry.
(process_relocs): Don't crash if relocation or symbol section's
sh_link is invalid.
(slurp_ia64_unwind_table, slurp_hppa_unwind_table): Don't crash if
relocation section's sh_info is invalid.
(ia64_process_unwind, hppa_process_unwind): Don't crash if symbol
table's sh_link is invalid.
(process_version_sections): Don't crash on version or symbol
section's sh_link is invalid.  Don't crash if symbol's st_shndx
is invalid.
(process_symbol_table): Don't crash if string table is corrupt
or symbol's st_name, st_shndx, vna_name or vda_name is invalid.
(debug_apply_rela_addends): Don't crash if relocation section's
sh_info or sh_link is invalid.
(display_debug_loc): Warn for unterminated .debug_loc section
or start offsets not within .debug_loc section boundaries.
(process_gnu_liblist): Don't crash if liblist section's sh_link
or entry's l_name is invalid.

binutils/ChangeLog
binutils/readelf.c

index 3117f14e418cb0e21c68d4784a3d0c5a3da3eb0e..4fa37ba9418c9717daaa5bd1e48708ccb030e76c 100644 (file)
@@ -1,3 +1,53 @@
+2005-06-14  Jakub Jelinek  <jakub@redhat.com>
+
+       * readelf.c (cmalloc, xcmalloc, xcrealloc): New functions.
+       (get_data): Add nmemb argument.  Return NULL if nmemb * size
+       overflows.  If var == NULL, allocate one extra byte and
+       clear it.
+       (slurp_rela_relocs, slurp_rel_relocs, get_32bit_program_headers,
+       get_64bit_program_headers, get_program_headers,
+       get_32bit_section_headers, get_64bit_section_headers,
+       get_32bit_elf_symbols, get_64bit_elf_symbols, process_section_headers,
+       process_section_groups, process_relocs, slurp_ia64_unwind_table,
+       ia64_process_unwind, slurp_hppa_unwind_table, hppa_process_unwind,
+       get_32bit_dynamic_section, get_64bit_dynamic_section,
+       process_dynamic_section, process_version_sections, get_dynamic_data,
+       process_symbol_table, dump_section, load_debug_str, load_debug_loc,
+       load_debug_range, read_and_display_attr_value, process_debug_info,
+       get_debug_info, frame_need_space, display_debug_frames,
+       display_debug_section, process_mips_specific, process_gnu_liblist,
+       process_corefile_note_segment): Adjust get_data callers.  Use
+       cmalloc, xcmalloc and xcrealloc instead of {m,xm,xre}alloc where
+       passed size is a product of 2 numbers.
+
+       * readelf.c (print_mode): Fix comment typo.
+       (slurp_rela_relocs, slurp_rel_relocs): Fix memory leaks.
+       (dump_relocations): Fix a thinko in check for invalid st_name.
+       (process_program_headers): Don't crash if string_table is NULL.
+       (process_section_headers): Don't crash if e_shstrndx is invalid.
+       Ensure string_table_length is 0 if string_table == NULL.
+       Don't return just because string_table is NULL.
+       (process_section_groups): Don't crash if symtab's sh_link or
+       symbol's st_name is invalid.  Fix a memory leak.  Fix check for
+       invalid section number entry.
+       (process_relocs): Don't crash if relocation or symbol section's
+       sh_link is invalid.
+       (slurp_ia64_unwind_table, slurp_hppa_unwind_table): Don't crash if
+       relocation section's sh_info is invalid.
+       (ia64_process_unwind, hppa_process_unwind): Don't crash if symbol
+       table's sh_link is invalid.
+       (process_version_sections): Don't crash on version or symbol
+       section's sh_link is invalid.  Don't crash if symbol's st_shndx
+       is invalid.
+       (process_symbol_table): Don't crash if string table is corrupt
+       or symbol's st_name, st_shndx, vna_name or vda_name is invalid.
+       (debug_apply_rela_addends): Don't crash if relocation section's
+       sh_info or sh_link is invalid.
+       (display_debug_loc): Warn for unterminated .debug_loc section
+       or start offsets not within .debug_loc section boundaries.
+       (process_gnu_liblist): Don't crash if liblist section's sh_link
+       or entry's l_name is invalid.
+
 2005-06-09  Jakub Jelinek  <jakub@redhat.com>
 
        * objdump.c (disassemble_bytes): Don't crash if q->howto == NULL.
index 33e30ddf3484f5732fb5917a669951ec4cf6c792..970fbc01d75d1a77f79100b8492f30529ba963c6 100644 (file)
@@ -207,7 +207,7 @@ unsigned int num_dump_sects = 0;
 #define DISASS_DUMP    (1 << 1)
 #define DEBUG_DUMP     (1 << 2)
 
-/* How to rpint a vma value.  */
+/* How to print a vma value.  */
 typedef enum print_mode
 {
   HEX,
@@ -287,11 +287,42 @@ warn (const char *message, ...)
 }
 
 static void *
-get_data (void *var, FILE *file, long offset, size_t size, const char *reason)
+cmalloc (size_t nmemb, size_t size)
+{
+  /* Check for overflow.  */
+  if (nmemb >= ~(size_t) 0 / size)
+    return NULL;
+  else
+    return malloc (nmemb * size);
+}
+
+static void *
+xcmalloc (size_t nmemb, size_t size)
+{
+  /* Check for overflow.  */
+  if (nmemb >= ~(size_t) 0 / size)
+    return NULL;
+  else
+    return xmalloc (nmemb * size);
+}
+
+static void *
+xcrealloc (void *ptr, size_t nmemb, size_t size)
+{
+  /* Check for overflow.  */
+  if (nmemb >= ~(size_t) 0 / size)
+    return NULL;
+  else
+    return xrealloc (ptr, nmemb * size);
+}
+
+static void *
+get_data (void *var, FILE *file, long offset, size_t size, size_t nmemb,
+         const char *reason)
 {
   void *mvar;
 
-  if (size == 0)
+  if (size == 0 || nmemb == 0)
     return NULL;
 
   if (fseek (file, archive_file_offset + offset, SEEK_SET))
@@ -304,19 +335,24 @@ get_data (void *var, FILE *file, long offset, size_t size, const char *reason)
   mvar = var;
   if (mvar == NULL)
     {
-      mvar = malloc (size);
+      /* Check for overflow.  */
+      if (nmemb < (~(size_t) 0 - 1) / size)
+       /* + 1 so that we can '\0' terminate invalid string table sections.  */
+       mvar = malloc (size * nmemb + 1);
 
       if (mvar == NULL)
        {
          error (_("Out of memory allocating 0x%x bytes for %s\n"),
-                size, reason);
+                size * nmemb, reason);
          return NULL;
        }
+
+      ((char *) mvar)[size * nmemb] = '\0';
     }
 
-  if (fread (mvar, size, 1, file) != 1)
+  if (fread (mvar, size, nmemb, file) != nmemb)
     {
-      error (_("Unable to read in 0x%x bytes of %s\n"), size, reason);
+      error (_("Unable to read in 0x%x bytes of %s\n"), size * nmemb, reason);
       if (mvar != var)
        free (mvar);
       return NULL;
@@ -771,16 +807,17 @@ slurp_rela_relocs (FILE *file,
     {
       Elf32_External_Rela *erelas;
 
-      erelas = get_data (NULL, file, rel_offset, rel_size, _("relocs"));
+      erelas = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
       if (!erelas)
        return 0;
 
       nrelas = rel_size / sizeof (Elf32_External_Rela);
 
-      relas = malloc (nrelas * sizeof (Elf_Internal_Rela));
+      relas = cmalloc (nrelas, sizeof (Elf_Internal_Rela));
 
       if (relas == NULL)
        {
+         free (erelas);
          error (_("out of memory parsing relocs"));
          return 0;
        }
@@ -798,16 +835,17 @@ slurp_rela_relocs (FILE *file,
     {
       Elf64_External_Rela *erelas;
 
-      erelas = get_data (NULL, file, rel_offset, rel_size, _("relocs"));
+      erelas = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
       if (!erelas)
        return 0;
 
       nrelas = rel_size / sizeof (Elf64_External_Rela);
 
-      relas = malloc (nrelas * sizeof (Elf_Internal_Rela));
+      relas = cmalloc (nrelas, sizeof (Elf_Internal_Rela));
 
       if (relas == NULL)
        {
+         free (erelas);
          error (_("out of memory parsing relocs"));
          return 0;
        }
@@ -841,16 +879,17 @@ slurp_rel_relocs (FILE *file,
     {
       Elf32_External_Rel *erels;
 
-      erels = get_data (NULL, file, rel_offset, rel_size, _("relocs"));
+      erels = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
       if (!erels)
        return 0;
 
       nrels = rel_size / sizeof (Elf32_External_Rel);
 
-      rels = malloc (nrels * sizeof (Elf_Internal_Rela));
+      rels = cmalloc (nrels, sizeof (Elf_Internal_Rela));
 
       if (rels == NULL)
        {
+         free (erels);
          error (_("out of memory parsing relocs"));
          return 0;
        }
@@ -868,16 +907,17 @@ slurp_rel_relocs (FILE *file,
     {
       Elf64_External_Rel *erels;
 
-      erels = get_data (NULL, file, rel_offset, rel_size, _("relocs"));
+      erels = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
       if (!erels)
        return 0;
 
       nrels = rel_size / sizeof (Elf64_External_Rel);
 
-      rels = malloc (nrels * sizeof (Elf_Internal_Rela));
+      rels = cmalloc (nrels, sizeof (Elf_Internal_Rela));
 
       if (rels == NULL)
        {
+         free (erels);
          error (_("out of memory parsing relocs"));
          return 0;
        }
@@ -1323,7 +1363,7 @@ dump_relocations (FILE *file,
                }
              else if (strtab == NULL)
                printf (_("<string table index: %3ld>"), psym->st_name);
-             else if (psym->st_name > strtablen)
+             else if (psym->st_name >= strtablen)
                printf (_("<corrupt string table index: %3ld>"), psym->st_name);
              else
                print_symbol (22, strtab + psym->st_name);
@@ -3151,7 +3191,7 @@ get_32bit_program_headers (FILE *file, Elf_Internal_Phdr *program_headers)
   unsigned int i;
 
   phdrs = get_data (NULL, file, elf_header.e_phoff,
-                   elf_header.e_phentsize * elf_header.e_phnum,
+                   elf_header.e_phentsize, elf_header.e_phnum,
                    _("program headers"));
   if (!phdrs)
     return 0;
@@ -3184,7 +3224,7 @@ get_64bit_program_headers (FILE *file, Elf_Internal_Phdr *program_headers)
   unsigned int i;
 
   phdrs = get_data (NULL, file, elf_header.e_phoff,
-                   elf_header.e_phentsize * elf_header.e_phnum,
+                   elf_header.e_phentsize, elf_header.e_phnum,
                    _("program headers"));
   if (!phdrs)
     return 0;
@@ -3219,7 +3259,7 @@ get_program_headers (FILE *file)
   if (program_headers != NULL)
     return 1;
 
-  phdrs = malloc (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
+  phdrs = cmalloc (elf_header.e_phnum, sizeof (Elf_Internal_Phdr));
 
   if (phdrs == NULL)
     {
@@ -3432,13 +3472,11 @@ process_program_headers (FILE *file)
        putc ('\n', stdout);
     }
 
-  if (do_segments && section_headers != NULL)
+  if (do_segments && section_headers != NULL && string_table != NULL)
     {
       printf (_("\n Section to Segment mapping:\n"));
       printf (_("  Segment Sections...\n"));
 
-      assert (string_table != NULL);
-
       for (i = 0; i < elf_header.e_phnum; i++)
        {
          unsigned int j;
@@ -3516,11 +3554,11 @@ get_32bit_section_headers (FILE *file, unsigned int num)
   unsigned int i;
 
   shdrs = get_data (NULL, file, elf_header.e_shoff,
-                   elf_header.e_shentsize * num, _("section headers"));
+                   elf_header.e_shentsize, num, _("section headers"));
   if (!shdrs)
     return 0;
 
-  section_headers = malloc (num * sizeof (Elf_Internal_Shdr));
+  section_headers = cmalloc (num, sizeof (Elf_Internal_Shdr));
 
   if (section_headers == NULL)
     {
@@ -3557,11 +3595,11 @@ get_64bit_section_headers (FILE *file, unsigned int num)
   unsigned int i;
 
   shdrs = get_data (NULL, file, elf_header.e_shoff,
-                   elf_header.e_shentsize * num, _("section headers"));
+                   elf_header.e_shentsize, num, _("section headers"));
   if (!shdrs)
     return 0;
 
-  section_headers = malloc (num * sizeof (Elf_Internal_Shdr));
+  section_headers = cmalloc (num, sizeof (Elf_Internal_Shdr));
 
   if (section_headers == NULL)
     {
@@ -3600,7 +3638,7 @@ get_32bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
   Elf_Internal_Sym *psym;
   unsigned int j;
 
-  esyms = get_data (NULL, file, section->sh_offset, section->sh_size,
+  esyms = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
                    _("symbols"));
   if (!esyms)
     return NULL;
@@ -3611,7 +3649,7 @@ get_32bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
          == (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
     {
       shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset,
-                       symtab_shndx_hdr->sh_size, _("symtab shndx"));
+                       1, symtab_shndx_hdr->sh_size, _("symtab shndx"));
       if (!shndx)
        {
          free (esyms);
@@ -3620,7 +3658,7 @@ get_32bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
     }
 
   number = section->sh_size / section->sh_entsize;
-  isyms = malloc (number * sizeof (Elf_Internal_Sym));
+  isyms = cmalloc (number, sizeof (Elf_Internal_Sym));
 
   if (isyms == NULL)
     {
@@ -3663,7 +3701,7 @@ get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
   Elf_Internal_Sym *psym;
   unsigned int j;
 
-  esyms = get_data (NULL, file, section->sh_offset, section->sh_size,
+  esyms = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
                    _("symbols"));
   if (!esyms)
     return NULL;
@@ -3674,7 +3712,7 @@ get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
          == (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
     {
       shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset,
-                       symtab_shndx_hdr->sh_size, _("symtab shndx"));
+                       1, symtab_shndx_hdr->sh_size, _("symtab shndx"));
       if (!shndx)
        {
          free (esyms);
@@ -3683,7 +3721,7 @@ get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
     }
 
   number = section->sh_size / section->sh_entsize;
-  isyms = malloc (number * sizeof (Elf_Internal_Sym));
+  isyms = cmalloc (number, sizeof (Elf_Internal_Sym));
 
   if (isyms == NULL)
     {
@@ -3793,17 +3831,17 @@ process_section_headers (FILE *file)
     return 0;
 
   /* Read in the string table, so that we have names to display.  */
-  section = SECTION_HEADER (elf_header.e_shstrndx);
-
-  if (section->sh_size != 0)
+  if (SECTION_HEADER_INDEX (elf_header.e_shstrndx) < elf_header.e_shnum)
     {
-      string_table = get_data (NULL, file, section->sh_offset,
-                              section->sh_size, _("string table"));
+      section = SECTION_HEADER (elf_header.e_shstrndx);
 
-      if (string_table == NULL)
-       return 0;
+      if (section->sh_size != 0)
+       {
+         string_table = get_data (NULL, file, section->sh_offset,
+                                  1, section->sh_size, _("string table"));
 
-      string_table_length = section->sh_size;
+         string_table_length = string_table != NULL ? section->sh_size : 0;
+       }
     }
 
   /* Scan the sections for the dynamic symbol table
@@ -3860,7 +3898,7 @@ process_section_headers (FILE *file)
            }
 
          dynamic_strings = get_data (NULL, file, section->sh_offset,
-                                     section->sh_size, _("dynamic strings"));
+                                     1, section->sh_size, _("dynamic strings"));
          dynamic_strings_length = section->sh_size;
        }
       else if (section->sh_type == SHT_SYMTAB_SHNDX)
@@ -4106,6 +4144,7 @@ process_section_groups (FILE *file)
   Elf_Internal_Shdr *symtab_sec, *strtab_sec;
   Elf_Internal_Sym *symtab;
   char *strtab;
+  size_t strtab_size;
 
   /* Don't process section groups unless needed.  */
   if (!do_unwind && !do_section_groups)
@@ -4162,6 +4201,7 @@ process_section_groups (FILE *file)
   strtab_sec = NULL;
   symtab = NULL;
   strtab = NULL;
+  strtab_size = 0;
   for (i = 0, section = section_headers, group = section_groups;
        i < elf_header.e_shnum;
        i++, section++)
@@ -4176,8 +4216,9 @@ process_section_groups (FILE *file)
          Elf_Internal_Sym *sym;
 
          /* Get the symbol table.  */
-         sec = SECTION_HEADER (section->sh_link);
-         if (sec->sh_type != SHT_SYMTAB)
+         if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum
+             || ((sec = SECTION_HEADER (section->sh_link))->sh_type
+                 != SHT_SYMTAB))
            {
              error (_("Bad sh_link in group section `%s'\n"), name);
              continue;
@@ -4203,26 +4244,41 @@ process_section_groups (FILE *file)
                }
 
              group_name = SECTION_NAME (section_headers + sec_index);
+             strtab_sec = NULL;
+             if (strtab)
+               free (strtab);
              strtab = NULL;
+             strtab_size = 0;
            }
          else
            {
              /* Get the string table.  */
-             sec = SECTION_HEADER (symtab_sec->sh_link);
-             if (strtab_sec != sec)
+             if (SECTION_HEADER_INDEX (symtab_sec->sh_link)
+                 >= elf_header.e_shnum)
+               {
+                 strtab_sec = NULL;
+                 if (strtab)
+                   free (strtab);
+                 strtab = NULL;
+                 strtab_size = 0;
+               }
+             else if (strtab_sec
+                      != (sec = SECTION_HEADER (symtab_sec->sh_link)))
                {
                  strtab_sec = sec;
                  if (strtab)
                    free (strtab);
                  strtab = get_data (NULL, file, strtab_sec->sh_offset,
-                                    strtab_sec->sh_size,
+                                    1, strtab_sec->sh_size,
                                     _("string table"));
+                 strtab_size = strtab != NULL ? strtab_sec->sh_size : 0;
                }
-             group_name = strtab + sym->st_name;
+             group_name = sym->st_name < strtab_size
+                          ? strtab + sym->st_name : "<corrupt>";
            }
 
          start = get_data (NULL, file, section->sh_offset,
-                           section->sh_size, _("section data"));
+                           1, section->sh_size, _("section data"));
 
          indices = start;
          size = (section->sh_size / section->sh_entsize) - 1;
@@ -4246,7 +4302,7 @@ process_section_groups (FILE *file)
              entry = byte_get (indices, 4);
              indices += 4;
 
-             if (entry >= elf_header.e_shnum)
+             if (SECTION_HEADER_INDEX (entry) >= elf_header.e_shnum)
                {
                  error (_("section [%5u] in group section [%5u] > maximum section [%5u]\n"),
                         entry, i, elf_header.e_shnum - 1);
@@ -4290,8 +4346,7 @@ process_section_groups (FILE *file)
              if (do_section_groups)
                {
                  sec = SECTION_HEADER (entry);
-                 printf ("   [%5u]   %s\n",
-                         entry, SECTION_NAME (sec));
+                 printf ("   [%5u]   %s\n", entry, SECTION_NAME (sec));
                }
 
              g = xmalloc (sizeof (struct group_list));
@@ -4422,12 +4477,14 @@ process_relocs (FILE *file)
 
              is_rela = section->sh_type == SHT_RELA;
 
-             if (section->sh_link)
+             if (section->sh_link
+                 && SECTION_HEADER_INDEX (section->sh_link)
+                    < elf_header.e_shnum)
                {
                  Elf_Internal_Shdr *symsec;
                  Elf_Internal_Sym *symtab;
                  unsigned long nsyms;
-                 unsigned long strtablen;
+                 unsigned long strtablen = 0;
                  char *strtab = NULL;
 
                  symsec = SECTION_HEADER (section->sh_link);
@@ -4437,11 +4494,16 @@ process_relocs (FILE *file)
                  if (symtab == NULL)
                    continue;
 
-                 strsec = SECTION_HEADER (symsec->sh_link);
+                 if (SECTION_HEADER_INDEX (symsec->sh_link)
+                     < elf_header.e_shnum)
+                   {
+                     strsec = SECTION_HEADER (symsec->sh_link);
 
-                 strtab = get_data (NULL, file, strsec->sh_offset,
-                                    strsec->sh_size, _("string table"));
-                 strtablen = strtab == NULL ? 0 : strsec->sh_size;
+                     strtab = get_data (NULL, file, strsec->sh_offset,
+                                        1, strsec->sh_size,
+                                        _("string table"));
+                     strtablen = strtab == NULL ? 0 : strsec->sh_size;
+                   }
 
                  dump_relocations (file, rel_offset, rel_size,
                                    symtab, nsyms, strtab, strtablen, is_rela);
@@ -4632,11 +4694,11 @@ slurp_ia64_unwind_table (FILE *file,
 
   /* Second, build the unwind table from the contents of the unwind section:  */
   size = sec->sh_size;
-  table = get_data (NULL, file, sec->sh_offset, size, _("unwind table"));
+  table = get_data (NULL, file, sec->sh_offset, 1, size, _("unwind table"));
   if (!table)
     return 0;
 
-  aux->table = xmalloc (size / (3 * eh_addr_size) * sizeof (aux->table[0]));
+  aux->table = xcmalloc (size / (3 * eh_addr_size), sizeof (aux->table[0]));
   tep = aux->table;
   for (tp = table; tp < table + size; tp += 3 * eh_addr_size, ++tep)
     {
@@ -4668,6 +4730,7 @@ slurp_ia64_unwind_table (FILE *file,
        ++relsec)
     {
       if (relsec->sh_type != SHT_RELA
+         || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
          || SECTION_HEADER (relsec->sh_info) != sec)
        continue;
 
@@ -4733,15 +4796,16 @@ ia64_process_unwind (FILE *file)
 
   for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
     {
-      if (sec->sh_type == SHT_SYMTAB)
+      if (sec->sh_type == SHT_SYMTAB
+         && SECTION_HEADER_INDEX (sec->sh_link) < elf_header.e_shnum)
        {
          aux.nsyms = sec->sh_size / sec->sh_entsize;
          aux.symtab = GET_ELF_SYMBOLS (file, sec);
 
          strsec = SECTION_HEADER (sec->sh_link);
-         aux.strtab_size = strsec->sh_size;
          aux.strtab = get_data (NULL, file, strsec->sh_offset,
-                                aux.strtab_size, _("string table"));
+                                1, strsec->sh_size, _("string table"));
+         aux.strtab_size = aux.strtab != NULL ? strsec->sh_size : 0;
        }
       else if (sec->sh_type == SHT_IA_64_UNWIND)
        unwcount++;
@@ -4822,7 +4886,7 @@ ia64_process_unwind (FILE *file)
        {
          aux.info_size = sec->sh_size;
          aux.info_addr = sec->sh_addr;
-         aux.info = get_data (NULL, file, sec->sh_offset, aux.info_size,
+         aux.info = get_data (NULL, file, sec->sh_offset, 1, aux.info_size,
                               _("unwind info"));
 
          printf (_("\nUnwind section "));
@@ -5012,13 +5076,13 @@ slurp_hppa_unwind_table (FILE *file,
   /* Second, build the unwind table from the contents of the unwind
      section.  */
   size = sec->sh_size;
-  table = get_data (NULL, file, sec->sh_offset, size, _("unwind table"));
+  table = get_data (NULL, file, sec->sh_offset, 1, size, _("unwind table"));
   if (!table)
     return 0;
 
   unw_ent_size = 2 * eh_addr_size + 8;
 
-  tep = aux->table = xmalloc (size / unw_ent_size * sizeof (aux->table[0]));
+  tep = aux->table = xcmalloc (size / unw_ent_size, sizeof (aux->table[0]));
 
   for (tp = table; tp < table + size; tp += (2 * eh_addr_size + 8), ++tep)
     {
@@ -5086,6 +5150,7 @@ slurp_hppa_unwind_table (FILE *file,
        ++relsec)
     {
       if (relsec->sh_type != SHT_RELA
+         || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
          || SECTION_HEADER (relsec->sh_info) != sec)
        continue;
 
@@ -5149,19 +5214,21 @@ hppa_process_unwind (FILE *file)
 
   memset (& aux, 0, sizeof (aux));
 
-  assert (string_table != NULL);
+  if (string_table == NULL)
+    return 1;
 
   for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
     {
-      if (sec->sh_type == SHT_SYMTAB)
+      if (sec->sh_type == SHT_SYMTAB
+         && SECTION_HEADER_INDEX (sec->sh_link) < elf_header.e_shnum)
        {
          aux.nsyms = sec->sh_size / sec->sh_entsize;
          aux.symtab = GET_ELF_SYMBOLS (file, sec);
 
          strsec = SECTION_HEADER (sec->sh_link);
-         aux.strtab_size = strsec->sh_size;
          aux.strtab = get_data (NULL, file, strsec->sh_offset,
-                                aux.strtab_size, _("string table"));
+                                1, strsec->sh_size, _("string table"));
+         aux.strtab_size = aux.strtab != NULL ? strsec->sh_size : 0;
        }
       else if (streq (SECTION_NAME (sec), ".PARISC.unwind"))
        unwsec = sec;
@@ -5377,7 +5444,7 @@ get_32bit_dynamic_section (FILE *file)
   Elf32_External_Dyn *edyn, *ext;
   Elf_Internal_Dyn *entry;
 
-  edyn = get_data (NULL, file, dynamic_addr, dynamic_size,
+  edyn = get_data (NULL, file, dynamic_addr, 1, dynamic_size,
                   _("dynamic section"));
   if (!edyn)
     return 0;
@@ -5394,7 +5461,7 @@ get_32bit_dynamic_section (FILE *file)
        break;
     }
 
-  dynamic_section = malloc (dynamic_nent * sizeof (*entry));
+  dynamic_section = cmalloc (dynamic_nent, sizeof (*entry));
   if (dynamic_section == NULL)
     {
       error (_("Out of memory\n"));
@@ -5421,7 +5488,7 @@ get_64bit_dynamic_section (FILE *file)
   Elf64_External_Dyn *edyn, *ext;
   Elf_Internal_Dyn *entry;
 
-  edyn = get_data (NULL, file, dynamic_addr, dynamic_size,
+  edyn = get_data (NULL, file, dynamic_addr, 1, dynamic_size,
                   _("dynamic section"));
   if (!edyn)
     return 0;
@@ -5438,7 +5505,7 @@ get_64bit_dynamic_section (FILE *file)
        break;
     }
 
-  dynamic_section = malloc (dynamic_nent * sizeof (*entry));
+  dynamic_section = cmalloc (dynamic_nent, sizeof (*entry));
   if (dynamic_section == NULL)
     {
       error (_("Out of memory\n"));
@@ -5596,7 +5663,7 @@ process_dynamic_section (FILE *file)
              continue;
            }
 
-         dynamic_strings = get_data (NULL, file, offset, str_tab_len,
+         dynamic_strings = get_data (NULL, file, offset, 1, str_tab_len,
                                      _("dynamic string table"));
          dynamic_strings_length = str_tab_len;
          break;
@@ -5631,8 +5698,8 @@ process_dynamic_section (FILE *file)
          Elf_Internal_Syminfo *syminfo;
 
          /* There is a syminfo section.  Read the data.  */
-         extsyminfo = get_data (NULL, file, dynamic_syminfo_offset, syminsz,
-                                _("symbol information"));
+         extsyminfo = get_data (NULL, file, dynamic_syminfo_offset, 1,
+                                syminsz, _("symbol information"));
          if (!extsyminfo)
            return 0;
 
@@ -6108,9 +6175,13 @@ process_version_sections (FILE *file)
            printf_vma (section->sh_addr);
            printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
                    (unsigned long) section->sh_offset, section->sh_link,
-                   SECTION_NAME (SECTION_HEADER (section->sh_link)));
+                   SECTION_HEADER_INDEX (section->sh_link)
+                   < elf_header.e_shnum
+                   ? SECTION_NAME (SECTION_HEADER (section->sh_link))
+                   : "<corrupt>");
 
-           edefs = get_data (NULL, file, section->sh_offset, section->sh_size,
+           edefs = get_data (NULL, file, section->sh_offset, 1,
+                             section->sh_size,
                              _("version definition section"));
            if (!edefs)
              break;
@@ -6197,9 +6268,13 @@ process_version_sections (FILE *file)
            printf_vma (section->sh_addr);
            printf (_("  Offset: %#08lx  Link to section: %ld (%s)\n"),
                    (unsigned long) section->sh_offset, section->sh_link,
-                   SECTION_NAME (SECTION_HEADER (section->sh_link)));
+                   SECTION_HEADER_INDEX (section->sh_link)
+                   < elf_header.e_shnum
+                   ? SECTION_NAME (SECTION_HEADER (section->sh_link))
+                   : "<corrupt>");
 
-           eneed = get_data (NULL, file, section->sh_offset, section->sh_size,
+           eneed = get_data (NULL, file, section->sh_offset, 1,
+                             section->sh_size,
                              _("version need section"));
            if (!eneed)
              break;
@@ -6279,16 +6354,23 @@ process_version_sections (FILE *file)
            Elf_Internal_Shdr *string_sec;
            long off;
 
+           if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum)
+             break;
+
            link_section = SECTION_HEADER (section->sh_link);
            total = section->sh_size / section->sh_entsize;
 
+           if (SECTION_HEADER_INDEX (link_section->sh_link)
+               >= elf_header.e_shnum)
+             break;
+
            found = 1;
 
            symbols = GET_ELF_SYMBOLS (file, link_section);
 
            string_sec = SECTION_HEADER (link_section->sh_link);
 
-           strtab = get_data (NULL, file, string_sec->sh_offset,
+           strtab = get_data (NULL, file, string_sec->sh_offset, 1,
                               string_sec->sh_size, _("version string table"));
            if (!strtab)
              break;
@@ -6305,7 +6387,7 @@ process_version_sections (FILE *file)
            off = offset_from_vma (file,
                                   version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
                                   total * sizeof (short));
-           edata = get_data (NULL, file, off, total * sizeof (short),
+           edata = get_data (NULL, file, off, total, sizeof (short),
                              _("version symbol data"));
            if (!edata)
              {
@@ -6313,7 +6395,7 @@ process_version_sections (FILE *file)
                break;
              }
 
-           data = malloc (total * sizeof (short));
+           data = cmalloc (total, sizeof (short));
 
            for (cnt = total; cnt --;)
              data[cnt] = byte_get (edata + cnt * sizeof (short),
@@ -6346,8 +6428,10 @@ process_version_sections (FILE *file)
 
                      check_def = 1;
                      check_need = 1;
-                     if (SECTION_HEADER (symbols[cnt + j].st_shndx)->sh_type
-                         != SHT_NOBITS)
+                     if (SECTION_HEADER_INDEX (symbols[cnt + j].st_shndx)
+                         >= elf_header.e_shnum
+                         || SECTION_HEADER (symbols[cnt + j].st_shndx)->sh_type
+                            != SHT_NOBITS)
                        {
                          if (symbols[cnt + j].st_shndx == SHN_UNDEF)
                            check_def = 0;
@@ -6372,7 +6456,7 @@ process_version_sections (FILE *file)
                              Elf_External_Vernaux evna;
                              unsigned long a_off;
 
-                             get_data (&evn, file, offset, sizeof (evn),
+                             get_data (&evn, file, offset, sizeof (evn), 1,
                                        _("version need"));
 
                              ivn.vn_aux  = BYTE_GET (evn.vn_aux);
@@ -6383,7 +6467,7 @@ process_version_sections (FILE *file)
                              do
                                {
                                  get_data (&evna, file, a_off, sizeof (evna),
-                                           _("version need aux (2)"));
+                                           1, _("version need aux (2)"));
 
                                  ivna.vna_next  = BYTE_GET (evna.vna_next);
                                  ivna.vna_other = BYTE_GET (evna.vna_other);
@@ -6424,7 +6508,7 @@ process_version_sections (FILE *file)
 
                          do
                            {
-                             get_data (&evd, file, offset, sizeof (evd),
+                             get_data (&evd, file, offset, sizeof (evd), 1,
                                        _("version def"));
 
                              ivd.vd_next = BYTE_GET (evd.vd_next);
@@ -6444,7 +6528,8 @@ process_version_sections (FILE *file)
 
                              get_data (&evda, file,
                                        offset - ivd.vd_next + ivd.vd_aux,
-                                       sizeof (evda), _("version def aux"));
+                                       sizeof (evda), 1,
+                                       _("version def aux"));
 
                              ivda.vda_name = BYTE_GET (evda.vda_name);
 
@@ -6596,7 +6681,7 @@ get_dynamic_data (FILE *file, unsigned int number, unsigned int ent_size)
   unsigned char *e_data;
   bfd_vma *i_data;
 
-  e_data = malloc (number * ent_size);
+  e_data = cmalloc (number, ent_size);
 
   if (e_data == NULL)
     {
@@ -6610,7 +6695,7 @@ get_dynamic_data (FILE *file, unsigned int number, unsigned int ent_size)
       return NULL;
     }
 
-  i_data = malloc (number * sizeof (*i_data));
+  i_data = cmalloc (number, sizeof (*i_data));
 
   if (i_data == NULL)
     {
@@ -6738,7 +6823,8 @@ process_symbol_table (FILE *file)
           i++, section++)
        {
          unsigned int si;
-         char *strtab;
+         char *strtab = NULL;
+         unsigned long int strtab_size = 0;
          Elf_Internal_Sym *symtab;
          Elf_Internal_Sym *psym;
 
@@ -6760,15 +6846,19 @@ process_symbol_table (FILE *file)
            continue;
 
          if (section->sh_link == elf_header.e_shstrndx)
-           strtab = string_table;
-         else
+           {
+             strtab = string_table;
+             strtab_size = string_table_length;
+           }
+         else if (SECTION_HEADER_INDEX (section->sh_link) < elf_header.e_shnum)
            {
              Elf_Internal_Shdr *string_sec;
 
              string_sec = SECTION_HEADER (section->sh_link);
 
              strtab = get_data (NULL, file, string_sec->sh_offset,
-                                string_sec->sh_size, _("string table"));
+                                1, string_sec->sh_size, _("string table"));
+             strtab_size = strtab != NULL ? string_sec->sh_size : 0;
            }
 
          for (si = 0, psym = symtab;
@@ -6783,7 +6873,8 @@ process_symbol_table (FILE *file)
              printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
              printf (" %-3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
              printf (" %4s ", get_symbol_index_type (psym->st_shndx));
-             print_symbol (25, strtab + psym->st_name);
+             print_symbol (25, psym->st_name < strtab_size
+                           ? strtab + psym->st_name : "<corrupt>");
 
              if (section->sh_type == SHT_DYNSYM &&
                  version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
@@ -6799,12 +6890,14 @@ process_symbol_table (FILE *file)
                     sizeof data + si * sizeof (vers_data));
 
                  get_data (&data, file, offset + si * sizeof (vers_data),
-                           sizeof (data), _("version data"));
+                           sizeof (data), 1, _("version data"));
 
                  vers_data = byte_get (data, 2);
 
-                 is_nobits = (SECTION_HEADER (psym->st_shndx)->sh_type
-                              == SHT_NOBITS);
+                 is_nobits = (SECTION_HEADER_INDEX (psym->st_shndx)
+                              < elf_header.e_shnum
+                              && SECTION_HEADER (psym->st_shndx)->sh_type
+                                 == SHT_NOBITS);
 
                  check_def = (psym->st_shndx != SHN_UNDEF);
 
@@ -6826,7 +6919,7 @@ process_symbol_table (FILE *file)
                            {
                              unsigned long vna_off;
 
-                             get_data (&evn, file, offset, sizeof (evn),
+                             get_data (&evn, file, offset, sizeof (evn), 1,
                                        _("version need"));
 
                              ivn.vn_aux  = BYTE_GET (evn.vn_aux);
@@ -6839,7 +6932,7 @@ process_symbol_table (FILE *file)
                                  Elf_External_Vernaux evna;
 
                                  get_data (&evna, file, vna_off,
-                                           sizeof (evna),
+                                           sizeof (evna), 1,
                                            _("version need aux (3)"));
 
                                  ivna.vna_other = BYTE_GET (evna.vna_other);
@@ -6861,7 +6954,9 @@ process_symbol_table (FILE *file)
                          if (ivna.vna_other == vers_data)
                            {
                              printf ("@%s (%d)",
-                                     strtab + ivna.vna_name, ivna.vna_other);
+                                     ivna.vna_name < strtab_size
+                                     ? strtab + ivna.vna_name : "<corrupt>",
+                                     ivna.vna_other);
                              check_def = 0;
                            }
                          else if (! is_nobits)
@@ -6890,7 +6985,7 @@ process_symbol_table (FILE *file)
                                  Elf_External_Verdef evd;
 
                                  get_data (&evd, file, offset, sizeof (evd),
-                                           _("version def"));
+                                           1, _("version def"));
 
                                  ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
                                  ivd.vd_aux = BYTE_GET (evd.vd_aux);
@@ -6905,14 +7000,15 @@ process_symbol_table (FILE *file)
                              offset += ivd.vd_aux;
 
                              get_data (&evda, file, offset, sizeof (evda),
-                                       _("version def aux"));
+                                       1, _("version def aux"));
 
                              ivda.vda_name = BYTE_GET (evda.vda_name);
 
                              if (psym->st_name != ivda.vda_name)
                                printf ((vers_data & 0x8000)
                                        ? "@%s" : "@@%s",
-                                       strtab + ivda.vda_name);
+                                       ivda.vda_name < strtab_size
+                                       ? strtab + ivda.vda_name : "<corrupt>");
                            }
                        }
                    }
@@ -7097,7 +7193,8 @@ dump_section (Elf_Internal_Shdr *section, FILE *file)
 
   addr = section->sh_addr;
 
-  start = get_data (NULL, file, section->sh_offset, bytes, _("section data"));
+  start = get_data (NULL, file, section->sh_offset, 1, bytes,
+                   _("section data"));
   if (!start)
     return 0;
 
@@ -7304,7 +7401,7 @@ load_debug_str (FILE *file)
 
   debug_str_size = sec->sh_size;
 
-  debug_str_contents = get_data (NULL, file, sec->sh_offset, sec->sh_size,
+  debug_str_contents = get_data (NULL, file, sec->sh_offset, 1, sec->sh_size,
                                 _("debug_str section data"));
 }
 
@@ -7353,7 +7450,7 @@ load_debug_loc (FILE *file)
 
   debug_loc_size = sec->sh_size;
 
-  debug_loc_contents = get_data (NULL, file, sec->sh_offset, sec->sh_size,
+  debug_loc_contents = get_data (NULL, file, sec->sh_offset, 1, sec->sh_size,
                                 _("debug_loc section data"));
 }
 
@@ -7387,7 +7484,7 @@ load_debug_range (FILE *file)
 
   debug_range_size = sec->sh_size;
 
-  debug_range_contents = get_data (NULL, file, sec->sh_offset, sec->sh_size,
+  debug_range_contents = get_data (NULL, file, sec->sh_offset, 1, sec->sh_size,
                                   _("debug_range section data"));
 }
 
@@ -7428,8 +7525,10 @@ debug_apply_rela_addends (FILE *file,
       Elf_Internal_Sym *sym;
 
       if (relsec->sh_type != SHT_RELA
+         || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
          || SECTION_HEADER (relsec->sh_info) != section
-         || relsec->sh_size == 0)
+         || relsec->sh_size == 0
+         || SECTION_HEADER_INDEX (relsec->sh_link) >= elf_header.e_shnum)
        continue;
 
       if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
@@ -8367,11 +8466,11 @@ read_and_display_attr_value (unsigned long attribute,
                {
                  max += 1024;
                  debug_info_p->loc_offsets
-                   = xrealloc (debug_info_p->loc_offsets,
-                               max * sizeof (*debug_info_p->loc_offsets));
+                   = xcrealloc (debug_info_p->loc_offsets,
+                                max, sizeof (*debug_info_p->loc_offsets));
                  debug_info_p->have_frame_base
-                   = xrealloc (debug_info_p->have_frame_base,
-                               max * sizeof (*debug_info_p->have_frame_base));
+                   = xcrealloc (debug_info_p->have_frame_base,
+                                max, sizeof (*debug_info_p->have_frame_base));
                  debug_info_p->max_loc_offsets = max;
                }
              debug_info_p->loc_offsets [num] = uvalue;
@@ -8396,8 +8495,8 @@ read_and_display_attr_value (unsigned long attribute,
                {
                  max += 1024;
                  debug_info_p->range_lists
-                   = xrealloc (debug_info_p->range_lists,
-                               max * sizeof (*debug_info_p->range_lists));
+                   = xcrealloc (debug_info_p->range_lists,
+                                max, sizeof (*debug_info_p->range_lists));
                  debug_info_p->max_range_lists = max;
                }
              debug_info_p->range_lists [num] = uvalue;
@@ -8774,8 +8873,8 @@ process_debug_info (Elf_Internal_Shdr *section, unsigned char *start,
        }
 
       /* Then allocate an array to hold the information.  */
-      debug_information = malloc (num_units *
-                                 sizeof (* debug_information));
+      debug_information = cmalloc (num_units,
+                                  sizeof (* debug_information));
       if (debug_information == NULL)
        {
          error (_("Not enough memory for a debug info array of %u entries"),
@@ -8888,7 +8987,7 @@ process_debug_info (Elf_Internal_Shdr *section, unsigned char *start,
            return 0;
          }
 
-       begin = get_data (NULL, file, sec->sh_offset, sec->sh_size,
+       begin = get_data (NULL, file, sec->sh_offset, 1, sec->sh_size,
                          _("debug_abbrev section data"));
        if (!begin)
          return 0;
@@ -9057,7 +9156,7 @@ get_debug_info (FILE * file)
   if (section == NULL)
     return 0;
 
-  start = get_data (NULL, file, section->sh_offset, section->sh_size,
+  start = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
                    _("extracting information from .debug_info section"));
   if (start == NULL)
     return 0;
@@ -9678,8 +9777,22 @@ display_debug_loc (Elf_Internal_Shdr *section,
            }
          start = next;
 
+         if (offset >= bytes)
+           {
+             warn (_("Offset 0x%lx is bigger than .debug_loc section size.\n"),
+                   offset);
+             continue;
+           }
+
          while (1)
            {
+             if (start + 2 * pointer_size > section_end)
+               {
+                 warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
+                       offset);
+                 break;
+               }
+
              begin = byte_get (start, pointer_size);
              start += pointer_size;
              end = byte_get (start, pointer_size);
@@ -9695,14 +9808,28 @@ display_debug_loc (Elf_Internal_Shdr *section,
              if (begin == -1UL && end != -1UL)
                {
                  base_address = end;
-                 printf ("    %8.8lx %8.8lx %8.8lx (base address)\n",
+                 printf (_("    %8.8lx %8.8lx %8.8lx (base address)\n"),
                          offset, begin, end);
                  continue;
                }
 
+             if (start + 2 > section_end)
+               {
+                 warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
+                       offset);
+                 break;
+               }
+
              length = byte_get (start, 2);
              start += 2;
 
+             if (start + length > section_end)
+               {
+                 warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
+                       offset);
+                 break;
+               }
+
              printf ("    %8.8lx %8.8lx %8.8lx (",
                      offset, begin + base_address, end + base_address);
              need_frame_base = decode_location_expression (start,
@@ -10075,8 +10202,8 @@ frame_need_space (Frame_Chunk *fc, int reg)
     return;
 
   fc->ncols = reg + 1;
-  fc->col_type = xrealloc (fc->col_type, fc->ncols * sizeof (short int));
-  fc->col_offset = xrealloc (fc->col_offset, fc->ncols * sizeof (int));
+  fc->col_type = xcrealloc (fc->col_type, fc->ncols, sizeof (short int));
+  fc->col_offset = xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
 
   while (prev < fc->ncols)
     {
@@ -10386,8 +10513,8 @@ display_debug_frames (Elf_Internal_Shdr *section,
          else
            {
              fc->ncols = cie->ncols;
-             fc->col_type = xmalloc (fc->ncols * sizeof (short int));
-             fc->col_offset = xmalloc (fc->ncols * sizeof (int));
+             fc->col_type = xcmalloc (fc->ncols, sizeof (short int));
+             fc->col_offset = xcmalloc (fc->ncols, sizeof (int));
              memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int));
              memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int));
              fc->augmentation = cie->augmentation;
@@ -10699,8 +10826,8 @@ display_debug_frames (Elf_Internal_Shdr *section,
                printf ("  DW_CFA_remember_state\n");
              rs = xmalloc (sizeof (Frame_Chunk));
              rs->ncols = fc->ncols;
-             rs->col_type = xmalloc (rs->ncols * sizeof (short int));
-             rs->col_offset = xmalloc (rs->ncols * sizeof (int));
+             rs->col_type = xcmalloc (rs->ncols, sizeof (short int));
+             rs->col_offset = xcmalloc (rs->ncols, sizeof (int));
              memcpy (rs->col_type, fc->col_type, rs->ncols);
              memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int));
              rs->next = remembered_state;
@@ -10922,7 +11049,7 @@ display_debug_section (Elf_Internal_Shdr *section, FILE *file)
       {
        unsigned char *start;
 
-       start = get_data (NULL, file, section->sh_offset, length,
+       start = get_data (NULL, file, section->sh_offset, 1, length,
                          _("debug section data"));
        if (start == NULL)
          {
@@ -11048,7 +11175,7 @@ process_mips_specific (FILE *file)
       size_t cnt;
 
       elib = get_data (NULL, file, liblist_offset,
-                      liblistno * sizeof (Elf32_External_Lib),
+                      liblistno, sizeof (Elf32_External_Lib),
                       _("liblist"));
       if (elib)
        {
@@ -11137,11 +11264,11 @@ process_mips_specific (FILE *file)
       while (sect->sh_type != SHT_MIPS_OPTIONS)
        ++sect;
 
-      eopt = get_data (NULL, file, options_offset, sect->sh_size,
+      eopt = get_data (NULL, file, options_offset, 1, sect->sh_size,
                       _("options"));
       if (eopt)
        {
-         iopt = malloc ((sect->sh_size / sizeof (eopt)) * sizeof (*iopt));
+         iopt = cmalloc ((sect->sh_size / sizeof (eopt)), sizeof (*iopt));
          if (iopt == NULL)
            {
              error (_("Out of memory"));
@@ -11333,7 +11460,7 @@ process_mips_specific (FILE *file)
          return 0;
        }
 
-      iconf = malloc (conflictsno * sizeof (*iconf));
+      iconf = cmalloc (conflictsno, sizeof (*iconf));
       if (iconf == NULL)
        {
          error (_("Out of memory"));
@@ -11345,7 +11472,7 @@ process_mips_specific (FILE *file)
          Elf32_External_Conflict *econf32;
 
          econf32 = get_data (NULL, file, conflicts_offset,
-                             conflictsno * sizeof (*econf32), _("conflict"));
+                             conflictsno, sizeof (*econf32), _("conflict"));
          if (!econf32)
            return 0;
 
@@ -11359,7 +11486,7 @@ process_mips_specific (FILE *file)
          Elf64_External_Conflict *econf64;
 
          econf64 = get_data (NULL, file, conflicts_offset,
-                             conflictsno * sizeof (*econf64), _("conflict"));
+                             conflictsno, sizeof (*econf64), _("conflict"));
          if (!econf64)
            return 0;
 
@@ -11399,6 +11526,7 @@ process_gnu_liblist (FILE *file)
   Elf_Internal_Shdr *section, *string_sec;
   Elf32_External_Lib *elib;
   char *strtab;
+  size_t strtab_size;
   size_t cnt;
   unsigned i;
 
@@ -11412,15 +11540,19 @@ process_gnu_liblist (FILE *file)
       switch (section->sh_type)
        {
        case SHT_GNU_LIBLIST:
-         elib = get_data (NULL, file, section->sh_offset, section->sh_size,
+         if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum)
+           break;
+
+         elib = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
                           _("liblist"));
 
          if (elib == NULL)
            break;
          string_sec = SECTION_HEADER (section->sh_link);
 
-         strtab = get_data (NULL, file, string_sec->sh_offset,
+         strtab = get_data (NULL, file, string_sec->sh_offset, 1,
                             string_sec->sh_size, _("liblist string table"));
+         strtab_size = string_sec->sh_size;
 
          if (strtab == NULL
              || section->sh_entsize != sizeof (Elf32_External_Lib))
@@ -11457,9 +11589,11 @@ process_gnu_liblist (FILE *file)
 
              printf ("%3lu: ", (unsigned long) cnt);
              if (do_wide)
-               printf ("%-20s", strtab + liblist.l_name);
+               printf ("%-20s", liblist.l_name < strtab_size
+                                ? strtab + liblist.l_name : "<corrupt>");
              else
-               printf ("%-20.20s", strtab + liblist.l_name);
+               printf ("%-20.20s", liblist.l_name < strtab_size
+                                   ? strtab + liblist.l_name : "<corrupt>");
              printf (" %s %#010lx %-7ld %-7ld\n", timebuf, liblist.l_checksum,
                      liblist.l_version, liblist.l_flags);
            }
@@ -11624,7 +11758,7 @@ process_corefile_note_segment (FILE *file, bfd_vma offset, bfd_vma length)
   if (length <= 0)
     return 0;
 
-  pnotes = get_data (NULL, file, offset, length, _("notes"));
+  pnotes = get_data (NULL, file, offset, 1, length, _("notes"));
   if (!pnotes)
     return 0;