Fix buffer overflow regression due to minsym malloc-ed instead of obstack-ed.
[deliverable/binutils-gdb.git] / gdb / coffread.c
index e6ca7ed8aff008adeb33106bd42b1979697a32cf..4354741ab648948d3526768d235fad354cdf5e56 100644 (file)
@@ -58,7 +58,7 @@ struct coff_symfile_info
 
     CORE_ADDR textaddr;                /* Addr of .text section.  */
     unsigned int textsize;     /* Size of .text section.  */
-    struct stab_section_list *stabsects;       /* .stab sections.  */
+    std::vector<asection *> *stabsects;        /* .stab sections.  */
     asection *stabstrsect;     /* Section pointer for .stab section.  */
     char *stabstrdata;
   };
@@ -155,6 +155,12 @@ static int type_vector_length;
 
 #define INITIAL_TYPE_VECTOR_LENGTH 160
 
+static char *linetab = NULL;
+static long linetab_offset;
+static unsigned long linetab_size;
+
+static char *stringtab = NULL;
+
 extern void stabsread_clear_cache (void);
 
 static struct type *coff_read_struct_type (int, int, int,
@@ -185,21 +191,13 @@ static void patch_opaque_types (struct symtab *);
 
 static void enter_linenos (long, int, int, struct objfile *);
 
-static void free_linetab (void);
-
-static void free_linetab_cleanup (void *ignore);
-
-static int init_lineno (bfd *, long, int);
+static int init_lineno (bfd *, long, int, gdb::unique_xmalloc_ptr<char> *);
 
 static char *getsymname (struct internal_syment *);
 
 static const char *coff_getfilename (union internal_auxent *);
 
-static void free_stringtab (void);
-
-static void free_stringtab_cleanup (void *ignore);
-
-static int init_stringtab (bfd *, long);
+static int init_stringtab (bfd *, long, gdb::unique_xmalloc_ptr<char> *);
 
 static void read_one_sym (struct coff_symbol *,
                          struct internal_syment *,
@@ -249,21 +247,7 @@ coff_locate_sections (bfd *abfd, asection *sectp, void *csip)
        if (!isdigit (*s))
          break;
       if (*s == '\0')
-       {
-         struct stab_section_list *n, **pn;
-
-         n = XNEW (struct stab_section_list);
-         n->section = sectp;
-         n->next = NULL;
-         for (pn = &csi->stabsects; *pn != NULL; pn = &(*pn)->next)
-           ;
-         *pn = n;
-
-         /* This will be run after coffstab_build_psymtabs is called
-            in coff_symfile_read, at which point we no longer need
-            the information.  */
-         make_cleanup (xfree, n);
-       }
+       csi->stabsects->push_back (sectp);
     }
 }
 
@@ -385,10 +369,7 @@ coff_start_symtab (struct objfile *objfile, const char *name)
 {
   within_function = 0;
   start_symtab (objfile,
-  /* We fill in the filename later.  start_symtab puts this pointer
-     into last_source_file and we put it in subfiles->name, which
-     end_symtab frees; that's why it must be malloc'd.  */
-                xstrdup (name),
+               name,
   /* We never know the directory name for COFF.  */
                 NULL,
   /* The start address is irrelevant, since we call
@@ -482,7 +463,8 @@ record_minimal_symbol (minimal_symbol_reader &reader,
       return NULL;
     }
 
-  return reader.record_with_info (cs->c_name, address, type, section);
+  return reader.record_full (cs->c_name, strlen (cs->c_name), true, address,
+                            type, section);
 }
 \f
 /* coff_symfile_init ()
@@ -570,13 +552,16 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
   unsigned int num_symbols;
   int symtab_offset;
   int stringtab_offset;
-  struct cleanup *back_to;
   int stabstrsize;
   
   info = (struct coff_symfile_info *) objfile_data (objfile,
                                                    coff_objfile_data_key);
   symfile_bfd = abfd;          /* Kludge for swap routines.  */
 
+  std::vector<asection *> stabsects;
+  scoped_restore restore_stabsects
+    = make_scoped_restore (&info->stabsects, &stabsects);
+
 /* WARNING WILL ROBINSON!  ACCESSING BFD-PRIVATE DATA HERE!  FIXME!  */
   num_symbols = bfd_get_symcount (abfd);       /* How many syms */
   symtab_offset = cdata->sym_filepos;  /* Symbol table file offset */
@@ -595,10 +580,10 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
 
   /* Allocate space for raw symbol and aux entries, based on their
      space requirements as reported by BFD.  */
-  temp_sym = (char *) xmalloc
-    (cdata->local_symesz + cdata->local_auxesz);
+  gdb::def_vector<char> temp_storage (cdata->local_symesz
+                                     + cdata->local_auxesz);
+  temp_sym = temp_storage.data ();
   temp_aux = temp_sym + cdata->local_symesz;
-  back_to = make_cleanup (free_current_contents, &temp_sym);
 
   /* We need to know whether this is a PE file, because in PE files,
      unlike standard COFF files, symbol values are stored as offsets
@@ -628,22 +613,25 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
      can avoid spurious error messages (and maybe run a little
      faster!) by not even reading the line number table unless we have
      symbols.  */
+  scoped_restore restore_linetab = make_scoped_restore (&linetab);
+  gdb::unique_xmalloc_ptr<char> linetab_storage;
   if (num_symbols > 0)
     {
       /* Read the line number table, all at once.  */
       bfd_map_over_sections (abfd, find_linenos, (void *) info);
 
-      make_cleanup (free_linetab_cleanup, 0 /*ignore*/);
       val = init_lineno (abfd, info->min_lineno_offset,
-                         info->max_lineno_offset - info->min_lineno_offset);
+                         info->max_lineno_offset - info->min_lineno_offset,
+                        &linetab_storage);
       if (val < 0)
         error (_("\"%s\": error reading line numbers."), filename);
     }
 
   /* Now read the string table, all at once.  */
 
-  make_cleanup (free_stringtab_cleanup, 0 /*ignore*/);
-  val = init_stringtab (abfd, stringtab_offset);
+  scoped_restore restore_stringtab = make_scoped_restore (&stringtab);
+  gdb::unique_xmalloc_ptr<char> stringtab_storage;
+  val = init_stringtab (abfd, stringtab_offset, &stringtab_storage);
   if (val < 0)
     error (_("\"%s\": can't get string table"), filename);
 
@@ -661,7 +649,7 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
 
   if (pe_file)
     {
-      for (minimal_symbol *msym : objfile_msymbols (objfile))
+      for (minimal_symbol *msym : objfile->msymbols ())
        {
          const char *name = MSYMBOL_LINKAGE_NAME (msym);
 
@@ -701,7 +689,7 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
   if (!(objfile->flags & OBJF_READNEVER))
     bfd_map_over_sections (abfd, coff_locate_sections, (void *) info);
 
-  if (info->stabsects)
+  if (!info->stabsects->empty())
     {
       if (!info->stabstrsect)
        {
@@ -718,7 +706,7 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
 
       coffstab_build_psymtabs (objfile,
                               info->textaddr, info->textsize,
-                              info->stabsects,
+                              *info->stabsects,
                               info->stabstrsect->filepos, stabstrsize);
     }
   if (dwarf2_has_info (objfile, NULL))
@@ -745,8 +733,6 @@ coff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags)
                                    symfile_flags, objfile);
        }
     }
-
-  do_cleanups (back_to);
 }
 
 static void
@@ -1203,11 +1189,11 @@ coff_symtab_read (minimal_symbol_reader &reader,
   /* Patch up any opaque types (references to types that are not defined
      in the file where they are referenced, e.g. "struct foo *bar").  */
   {
-    struct compunit_symtab *cu;
-    struct symtab *s;
-
-    ALL_OBJFILE_FILETABS (objfile, cu, s)
-      patch_opaque_types (s);
+    for (compunit_symtab *cu : objfile->compunits ())
+      {
+       for (symtab *s : compunit_filetabs (cu))
+         patch_opaque_types (s);
+      }
   }
 
   coffread_objfile = NULL;
@@ -1298,17 +1284,13 @@ read_one_sym (struct coff_symbol *cs,
 \f
 /* Support for string table handling.  */
 
-static char *stringtab = NULL;
-
 static int
-init_stringtab (bfd *abfd, long offset)
+init_stringtab (bfd *abfd, long offset, gdb::unique_xmalloc_ptr<char> *storage)
 {
   long length;
   int val;
   unsigned char lengthbuf[4];
 
-  free_stringtab ();
-
   /* If the file is stripped, the offset might be zero, indicating no
      string table.  Just return with `stringtab' set to null.  */
   if (offset == 0)
@@ -1325,7 +1307,8 @@ init_stringtab (bfd *abfd, long offset)
   if (val != sizeof lengthbuf || length < sizeof lengthbuf)
     return 0;
 
-  stringtab = (char *) xmalloc (length);
+  storage->reset ((char *) xmalloc (length));
+  stringtab = storage->get ();
   /* This is in target format (probably not very useful, and not
      currently used), not host format.  */
   memcpy (stringtab, lengthbuf, sizeof lengthbuf);
@@ -1340,20 +1323,6 @@ init_stringtab (bfd *abfd, long offset)
   return 0;
 }
 
-static void
-free_stringtab (void)
-{
-  if (stringtab)
-    xfree (stringtab);
-  stringtab = NULL;
-}
-
-static void
-free_stringtab_cleanup (void *ignore)
-{
-  free_stringtab ();
-}
-
 static char *
 getsymname (struct internal_syment *symbol_entry)
 {
@@ -1407,24 +1376,19 @@ coff_getfilename (union internal_auxent *aux_entry)
 \f
 /* Support for line number handling.  */
 
-static char *linetab = NULL;
-static long linetab_offset;
-static unsigned long linetab_size;
-
 /* Read in all the line numbers for fast lookups later.  Leave them in
    external (unswapped) format in memory; we'll swap them as we enter
    them into GDB's data structures.  */
 
 static int
-init_lineno (bfd *abfd, long offset, int size)
+init_lineno (bfd *abfd, long offset, int size,
+            gdb::unique_xmalloc_ptr<char> *storage)
 {
   int val;
 
   linetab_offset = offset;
   linetab_size = size;
 
-  free_linetab ();
-
   if (size == 0)
     return 0;
 
@@ -1432,9 +1396,10 @@ init_lineno (bfd *abfd, long offset, int size)
     return -1;
 
   /* Allocate the desired table, plus a sentinel.  */
-  linetab = (char *) xmalloc (size + local_linesz);
+  storage->reset ((char *) xmalloc (size + local_linesz));
+  linetab = storage->get ();
 
-  val = bfd_bread (linetab, size, abfd);
+  val = bfd_bread (storage->get (), size, abfd);
   if (val != size)
     return -1;
 
@@ -1444,20 +1409,6 @@ init_lineno (bfd *abfd, long offset, int size)
   return 0;
 }
 
-static void
-free_linetab (void)
-{
-  if (linetab)
-    xfree (linetab);
-  linetab = NULL;
-}
-
-static void
-free_linetab_cleanup (void *ignore)
-{
-  free_linetab ();
-}
-
 #if !defined (L_LNNO32)
 #define L_LNNO32(lp) ((lp)->l_lnno)
 #endif
@@ -1545,7 +1496,7 @@ patch_type (struct type *type, struct type *real_type)
 static void
 patch_opaque_types (struct symtab *s)
 {
-  struct block *b;
+  const struct block *b;
   struct block_iterator iter;
   struct symbol *real_sym;
 
This page took 0.028182 seconds and 4 git commands to generate.