More fixes for invalid memory accesses, uncovered by valgrind and binary fuzzers.
authorNick Clifton <nickc@redhat.com>
Tue, 11 Nov 2014 15:34:27 +0000 (15:34 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 11 Nov 2014 15:34:27 +0000 (15:34 +0000)
PR binutils/17512
* coffcode.h (coff_slurp_line_table): Initialise the parts of the
line number cache that would not be initialised by the copy from
the new line number table.
(coff_classify_symbol): Allow for _bfd_coff_internal_syment_name
returning NULL.
* coffgen.c (coff_get_normalized_symbols): Get the external
symbols before allocating space for the internal symbols, in case
the get fails.
* elf.c (_bfd_elf_slurp_version_tables): Only allocate a verref
array if one is needed.  Likewise with the verdef array.
* peXXigen.c (_bfd_XXi_swap_sym_in): Replace abort()'s with error
messages.
(_bfd_XXi_swap_aux_in): Make sure that all fields of the aux
structure are initialised.
(pe_print_edata): Avoid reading off the end of the data buffer.

bfd/ChangeLog
bfd/coffcode.h
bfd/coffgen.c
bfd/elf.c
bfd/peXXigen.c

index 2e3e5a5..9f48d57 100644 (file)
@@ -1,3 +1,22 @@
+2014-11-11  Nick Clifton  <nickc@redhat.com>
+
+       PR binutils/17512
+       * coffcode.h (coff_slurp_line_table): Initialise the parts of the
+       line number cache that would not be initialised by the copy from
+       the new line number table.
+       (coff_classify_symbol): Allow for _bfd_coff_internal_syment_name
+       returning NULL.
+       * coffgen.c (coff_get_normalized_symbols): Get the external
+       symbols before allocating space for the internal symbols, in case
+       the get fails.
+       * elf.c (_bfd_elf_slurp_version_tables): Only allocate a verref
+       array if one is needed.  Likewise with the verdef array.
+       * peXXigen.c (_bfd_XXi_swap_sym_in): Replace abort()'s with error
+       messages.
+       (_bfd_XXi_swap_aux_in): Make sure that all fields of the aux
+       structure are initialised.
+       (pe_print_edata): Avoid reading off the end of the data buffer.
+
 2014-11-11  Alan Modra  <amodra@gmail.com>
 
        PR binutils/17512
index f10654e..4bc80bd 100644 (file)
@@ -4453,11 +4453,11 @@ buy_and_read (bfd *abfd, file_ptr where, bfd_size_type size)
   void * area = bfd_alloc (abfd, size);
 
   if (!area)
-    return (NULL);
+    return NULL;
   if (bfd_seek (abfd, where, SEEK_SET) != 0
       || bfd_bread (area, size, abfd) != size)
-    return (NULL);
-  return (area);
+    return NULL;
+  return area;
 }
 
 /*
@@ -4637,13 +4637,20 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
                  /* PR binutils/17512: Point the lineno to where
                     this entry will be after the memcpy below.  */
                  sym->lineno = lineno_cache + (n_cache_ptr - n_lineno_cache);
-
                  /* Copy the function and line number entries.  */
                  do
                    *n_cache_ptr++ = *old_ptr++;
                  while (old_ptr->line_number != 0);
                }
-             memcpy (lineno_cache, n_lineno_cache, amt);
+             /* PR 17521: file: 078-10659-0.004.  */
+             if (n_cache_ptr < n_lineno_cache + asect->lineno_count)
+               {
+                 amt = n_cache_ptr - n_lineno_cache;
+                 memcpy (lineno_cache, n_lineno_cache, amt * sizeof (alent));
+                 memset (lineno_cache + amt, 0, (asect->lineno_count - amt) * sizeof (alent));
+               }
+             else
+               memcpy (lineno_cache, n_lineno_cache, amt);
            }
          bfd_release (abfd, func_table);
        }
@@ -5074,13 +5081,13 @@ coff_classify_symbol (bfd *abfd,
       if (syment->n_value == 0)
        {
          asection *sec;
-         char buf[SYMNMLEN + 1];
-
-         sec = coff_section_from_bfd_index (abfd, syment->n_scnum);
-         if (sec != NULL
-             && (strcmp (bfd_get_section_name (abfd, sec),
-                         _bfd_coff_internal_syment_name (abfd, syment, buf))
-                 == 0))
+         char * name;
+         char buf[SYMNMLEN + 1];
+         name = _bfd_coff_internal_syment_name (abfd, syment, buf)
+         sec = coff_section_from_bfd_index (abfd, syment->n_scnum);
+         if (sec != NULL && name != NULL
+             && (strcmp (bfd_get_section_name (abfd, sec), name) == 0))
            return COFF_SYMBOL_PE_SECTION;
        }
 #endif
index 6c69902..aab88e3 100644 (file)
@@ -1758,15 +1758,15 @@ coff_get_normalized_symtab (bfd *abfd)
   if (obj_raw_syments (abfd) != NULL)
     return obj_raw_syments (abfd);
 
+  if (! _bfd_coff_get_external_symbols (abfd))
+    return NULL;
+
   size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);
   internal = (combined_entry_type *) bfd_zalloc (abfd, size);
   if (internal == NULL && size != 0)
     return NULL;
   internal_end = internal + obj_raw_syment_count (abfd);
   
-  if (! _bfd_coff_get_external_symbols (abfd))
-    return NULL;
-
   raw_src = (char *) obj_coff_external_syms (abfd);
 
   /* Mark the end of the symbols.  */
index 9c4dcdf..8b207ad 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -7269,8 +7269,12 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
 
       hdr = &elf_tdata (abfd)->dynverref_hdr;
 
-      elf_tdata (abfd)->verref = (Elf_Internal_Verneed *)
+      if (hdr->sh_info)
+       elf_tdata (abfd)->verref = (Elf_Internal_Verneed *)
           bfd_zalloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed));
+      else
+       elf_tdata (abfd)->verref = NULL;
+       
       if (elf_tdata (abfd)->verref == NULL)
        goto error_return;
 
@@ -7430,8 +7434,12 @@ error_return_verref:
          else
            freeidx = ++maxidx;
        }
-      elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *)
+      if (maxidx)
+       elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *)
           bfd_zalloc2 (abfd, maxidx, sizeof (Elf_Internal_Verdef));
+      else
+       elf_tdata (abfd)->verdef = NULL;
+
       if (elf_tdata (abfd)->verdef == NULL)
        goto error_return;
 
@@ -7572,16 +7580,12 @@ asymbol *
 _bfd_elf_make_empty_symbol (bfd *abfd)
 {
   elf_symbol_type *newsym;
-  bfd_size_type amt = sizeof (elf_symbol_type);
 
-  newsym = (elf_symbol_type *) bfd_zalloc (abfd, amt);
+  newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof * newsym);
   if (!newsym)
     return NULL;
-  else
-    {
-      newsym->symbol.the_bfd = abfd;
-      return &newsym->symbol;
-    }
+  newsym->symbol.the_bfd = abfd;
+  return &newsym->symbol;
 }
 
 void
index d1b33fd..725e9f6 100644 (file)
@@ -149,8 +149,13 @@ _bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1)
 
          name = _bfd_coff_internal_syment_name (abfd, in, namebuf);
          if (name == NULL)
-           /* FIXME: Return error.  */
-           abort ();
+           {
+             _bfd_error_handler (_("%B: unable to find name for empty section"),
+                                 abfd);
+             bfd_set_error (bfd_error_invalid_target);
+             return;
+           }
+
          sec = bfd_get_section_by_name (abfd, name);
          if (sec != NULL)
            in->n_scnum = sec->target_index;
@@ -170,15 +175,22 @@ _bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1)
            {
              name = (const char *) bfd_alloc (abfd, strlen (namebuf) + 1);
              if (name == NULL)
-               /* FIXME: Return error.  */
-               abort ();
+               {
+                 _bfd_error_handler (_("%B: out of memory creating name for empty section"),
+                                     abfd);
+                 return;
+               }
              strcpy ((char *) name, namebuf);
            }
+
          flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_DATA | SEC_LOAD;
          sec = bfd_make_section_anyway_with_flags (abfd, name, flags);
          if (sec == NULL)
-           /* FIXME: Return error.  */
-           abort ();
+           {
+             _bfd_error_handler (_("%B: unable to create fake empty section"),
+                                 abfd);
+             return;
+           }
 
          sec->vma = 0;
          sec->lma = 0;
@@ -283,6 +295,9 @@ _bfd_XXi_swap_aux_in (bfd * abfd,
   AUXENT *ext = (AUXENT *) ext1;
   union internal_auxent *in = (union internal_auxent *) in1;
 
+  /* PR 17521: Make sure that all fields in the aux structure
+     are initialised.  */
+  memset (in, 0, sizeof * in);
   switch (in_class)
     {
     case C_FILE:
@@ -1681,7 +1696,9 @@ pe_print_edata (bfd * abfd, void * vfile)
   bfd_fprintf_vma (abfd, file, edt.name);
 
   if ((edt.name >= adj) && (edt.name < adj + datasize))
-    fprintf (file, " %s\n", data + edt.name - adj);
+    fprintf (file, " %.*s\n",
+            (int) (datasize - (edt.name - adj)),
+            data + edt.name - adj);
   else
     fprintf (file, "(outside .edata section)\n");