objcopy write_debugging_info memory leaks
authorAlan Modra <amodra@gmail.com>
Wed, 5 Apr 2023 07:14:35 +0000 (16:44 +0930)
committerAlan Modra <amodra@gmail.com>
Thu, 6 Apr 2023 00:21:38 +0000 (09:51 +0930)
The old stabs code didn't bother too much about freeing memory.
This patch corrects that and avoids some dubious copying of strings.

* objcopy.c (write_debugging_info): Free both strings and
syms on failure to create sections.
* wrstabs.c: Delete unnecessary forward declarations and casts
throughout file.
(stab_write_symbol_and_free): New function.  Use it
throughout, simplifying return paths.
(stab_push_string): Don't strdup string.  Use it thoughout
for malloced strings.
(stab_push_string_dup): New function.  Use it throughout for
strings in auto buffers.
(write_stabs_in_sections_debugging_info): Free malloced memory.
(stab_enum_type): Increase buffer sizing for worst case.
(stab_range_type, stab_array_type): Reduce buffer size.
(stab_set_type): Likewise.
(stab_method_type): Free args on error return.  Correct
buffer size.
(stab_struct_field): Fix memory leaks.
(stab_class_static_member, stab_class_baseclass): Likewise.
(stab_start_class_type): Likewise.  Correct buffer size.
(stab_class_start_method): Correct buffer size.
(stab_class_method_var): Free memory on error return.
(stab_start_function): Fix "rettype" memory leak.

binutils/objcopy.c
binutils/wrstabs.c

index 957fb851432cb8abbbb905a1b9e84ea760bef28a..d4fc644640ca0523c40797489a93a6fcd1f7050f 100644 (file)
@@ -4667,6 +4667,7 @@ write_debugging_info (bfd *obfd, void *dhandle,
       flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING;
       stabsec = bfd_make_section_with_flags (obfd, ".stab", flags);
       stabstrsec = bfd_make_section_with_flags (obfd, ".stabstr", flags);
+      ret = true;
       if (stabsec == NULL
          || stabstrsec == NULL
          || !bfd_set_section_size (stabsec, symsize)
@@ -4676,18 +4677,17 @@ write_debugging_info (bfd *obfd, void *dhandle,
        {
          bfd_nonfatal_message (NULL, obfd, NULL,
                                _("can't create debugging section"));
-         free (strings);
-         return false;
+         ret = false;
        }
 
       /* We can get away with setting the section contents now because
         the next thing the caller is going to do is copy over the
         real sections.  We may someday have to split the contents
         setting out of this function.  */
-      ret = true;
-      if (! bfd_set_section_contents (obfd, stabsec, syms, 0, symsize)
-         || ! bfd_set_section_contents (obfd, stabstrsec, strings, 0,
-                                        stringsize))
+      if (ret
+         && (!bfd_set_section_contents (obfd, stabsec, syms, 0, symsize)
+             || !bfd_set_section_contents (obfd, stabstrsec, strings, 0,
+                                           stringsize)))
        {
          bfd_nonfatal_message (NULL, obfd, NULL,
                                _("can't set debugging section contents"));
index 53ade2eafbdea471bd1715de4ec9a3de1b02b3ab..b676374558b184d2fdf36e9862f7e63f1ec75ed9 100644 (file)
@@ -171,23 +171,6 @@ struct stab_write_handle
   const char *lineno_filename;
 };
 
-static struct bfd_hash_entry *string_hash_newfunc
-  (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
-static bool stab_write_symbol
-  (struct stab_write_handle *, int, int, bfd_vma, const char *);
-static bool stab_push_string
-  (struct stab_write_handle *, const char *, long, bool, unsigned int);
-static bool stab_push_defined_type
-  (struct stab_write_handle *, long, unsigned int);
-static char *stab_pop_type (struct stab_write_handle *);
-static bool stab_modify_type
-  (struct stab_write_handle *, int, unsigned int, long **, size_t *);
-static long stab_get_struct_index
-  (struct stab_write_handle *, const char *, unsigned int,
-   enum debug_type_kind, unsigned int *);
-static bool stab_class_method_var
-  (struct stab_write_handle *, const char *, enum debug_visibility,
-   bool, bool, bool, bfd_vma, bool);
 static bool stab_start_compilation_unit (void *, const char *);
 static bool stab_start_source (void *, const char *);
 static bool stab_empty_type (void *);
@@ -379,8 +362,7 @@ stab_write_symbol (struct stab_write_handle *info, int type, int desc,
   if (info->symbols_size + STAB_SYMBOL_SIZE > info->symbols_alloc)
     {
       info->symbols_alloc *= 2;
-      info->symbols = (bfd_byte *) xrealloc (info->symbols,
-                                            info->symbols_alloc);
+      info->symbols = xrealloc (info->symbols, info->symbols_alloc);
     }
 
   memcpy (info->symbols + info->symbols_size, sym, STAB_SYMBOL_SIZE);
@@ -390,16 +372,25 @@ stab_write_symbol (struct stab_write_handle *info, int type, int desc,
   return true;
 }
 
+static bool
+stab_write_symbol_and_free (struct stab_write_handle *info, int type, int desc,
+                           bfd_vma value, char *string)
+{
+  bool ret = stab_write_symbol (info, type, desc, value, string);
+  free (string);
+  return ret;
+}
+
 /* Push a string on to the type stack.  */
 
 static bool
-stab_push_string (struct stab_write_handle *info, const char *string,
+stab_push_string (struct stab_write_handle *info, char *string,
                  long tindex, bool definition, unsigned int size)
 {
   struct stab_type_stack *s;
 
-  s = (struct stab_type_stack *) xmalloc (sizeof *s);
-  s->string = xstrdup (string);
+  s = xmalloc (sizeof *s);
+  s->string = string;
   s->index = tindex;
   s->definition = definition;
   s->size = size;
@@ -415,6 +406,13 @@ stab_push_string (struct stab_write_handle *info, const char *string,
   return true;
 }
 
+static bool
+stab_push_string_dup (struct stab_write_handle *info, const char *string,
+                     long tindex, bool definition, unsigned int size)
+{
+  return stab_push_string (info, xstrdup (string), tindex, definition, size);
+}
+
 /* Push a type index which has already been defined.  */
 
 static bool
@@ -424,7 +422,7 @@ stab_push_defined_type (struct stab_write_handle *info, long tindex,
   char buf[20];
 
   sprintf (buf, "%ld", tindex);
-  return stab_push_string (info, buf, tindex, false, size);
+  return stab_push_string_dup (info, buf, tindex, false, size);
 }
 
 /* Pop a type off the type stack.  The caller is responsible for
@@ -466,14 +464,15 @@ write_stabs_in_sections_debugging_info (bfd *abfd, void *dhandle,
                                        bfd_size_type *pstringsize)
 {
   struct stab_write_handle info;
-  struct string_hash_entry *h;
+  struct string_hash_entry *h, *hnext;
   bfd_byte *p;
+  bool ret;
 
   memset (&info, 0, sizeof info);
   info.abfd = abfd;
 
   info.symbols_alloc = 500;
-  info.symbols = (bfd_byte *) xmalloc (info.symbols_alloc);
+  info.symbols = xmalloc (info.symbols_alloc);
 
   /* Reserve 1 byte for a null byte.  */
   info.strings_size = 1;
@@ -519,7 +518,7 @@ write_stabs_in_sections_debugging_info (bfd *abfd, void *dhandle,
   *psymsize = info.symbols_size;
 
   *pstringsize = info.strings_size;
-  *pstrings = (bfd_byte *) xmalloc (info.strings_size);
+  *pstrings = xmalloc (info.strings_size);
 
   p = *pstrings;
   *p++ = '\0';
@@ -529,17 +528,43 @@ write_stabs_in_sections_debugging_info (bfd *abfd, void *dhandle,
       p += strlen ((char *) p) + 1;
     }
 
-  bfd_hash_table_free (&info.typedef_hash.table);
-  bfd_hash_table_free (&info.strhash.table);
-  return true;
+  ret = true;
+  goto out;
 
  fail:
+  free (info.symbols);
+  ret = false;
+ out:
+  for (h = info.strings; h != NULL; h = hnext)
+    {
+      hnext = h->next;
+      free (h);
+    }
+  while (info.type_stack != NULL)
+    {
+      struct stab_type_stack *s = info.type_stack;
+      info.type_stack = s->next;
+      free (s->string);
+      free (s->fields);
+      if (s->baseclasses != NULL)
+       {
+         for (int i = 0; s->baseclasses[i] != NULL; i++)
+           free (s->baseclasses[i]);
+         free (s->baseclasses);
+       }
+      free (s->methods);
+      free (s->vtable);
+      free (s);
+    }
+  free (info.type_cache.pointer_types);
+  free (info.type_cache.function_types);
+  free (info.type_cache.reference_types);
+  free (info.type_cache.struct_types);
   if (info.typedef_hash.table.memory)
     bfd_hash_table_free (&info.typedef_hash.table);
   if (info.strhash.table.memory)
     bfd_hash_table_free (&info.strhash.table);
-  free (info.symbols);
-  return false;
+  return ret;
 }
 
 /* Start writing out information for a compilation unit.  */
@@ -598,7 +623,7 @@ stab_empty_type (void *p)
 
       sprintf (buf, "%ld=%ld", tindex, tindex);
 
-      return stab_push_string (info, buf, tindex, false, 0);
+      return stab_push_string_dup (info, buf, tindex, false, 0);
     }
 }
 
@@ -623,7 +648,7 @@ stab_void_type (void *p)
 
       sprintf (buf, "%ld=%ld", tindex, tindex);
 
-      return stab_push_string (info, buf, tindex, true, 0);
+      return stab_push_string_dup (info, buf, tindex, true, 0);
     }
 }
 
@@ -683,7 +708,7 @@ stab_int_type (void *p, unsigned int size, bool unsignedp)
            abort ();
        }
 
-      return stab_push_string (info, buf, tindex, true, size);
+      return stab_push_string_dup (info, buf, tindex, true, size);
     }
 }
 
@@ -724,7 +749,7 @@ stab_float_type (void *p, unsigned int size)
 
       free (int_type);
 
-      return stab_push_string (info, buf, tindex, true, size);
+      return stab_push_string_dup (info, buf, tindex, true, size);
     }
 }
 
@@ -742,7 +767,7 @@ stab_complex_type (void *p, unsigned int size)
 
   sprintf (buf, "%ld=r%ld;%u;0;", tindex, tindex, size);
 
-  return stab_push_string (info, buf, tindex, true, size * 2);
+  return stab_push_string_dup (info, buf, tindex, true, size * 2);
 }
 
 /* Push a bool type.  We use an XCOFF predefined type, since gdb
@@ -795,22 +820,19 @@ stab_enum_type (void *p, const char *tag, const char **names,
       if (tag == NULL)
        return false;
 
-      buf = (char *) xmalloc (10 + strlen (tag));
+      buf = xmalloc (4 + strlen (tag));
       sprintf (buf, "xe%s:", tag);
       /* FIXME: The size is just a guess.  */
-      if (! stab_push_string (info, buf, 0, false, 4))
-       return false;
-      free (buf);
-      return true;
+      return stab_push_string (info, buf, 0, false, 4);
     }
 
-  len = 10;
+  len = 25;
   if (tag != NULL)
     len += strlen (tag);
   for (pn = names; *pn != NULL; pn++)
-    len += strlen (*pn) + 20;
+    len += strlen (*pn) + 22;
 
-  buf = (char *) xmalloc (len);
+  buf = xmalloc (len);
 
   if (tag == NULL)
     strcpy (buf, "e");
@@ -828,20 +850,14 @@ stab_enum_type (void *p, const char *tag, const char **names,
   if (tag == NULL)
     {
       /* FIXME: The size is just a guess.  */
-      if (! stab_push_string (info, buf, 0, false, 4))
-       return false;
+      return stab_push_string (info, buf, 0, false, 4);
     }
   else
     {
       /* FIXME: The size is just a guess.  */
-      if (! stab_write_symbol (info, N_LSYM, 0, 0, buf)
-         || ! stab_push_defined_type (info, tindex, 4))
-       return false;
+      return (stab_write_symbol_and_free (info, N_LSYM, 0, 0, buf)
+             && stab_push_defined_type (info, tindex, 4));
     }
-
-  free (buf);
-
-  return true;
 }
 
 /* Push a modification of the top type on the stack.  Cache the
@@ -869,12 +885,10 @@ stab_modify_type (struct stab_write_handle *info, int mod,
          new type, so we don't bother to define one.  */
       definition = info->type_stack->definition;
       s = stab_pop_type (info);
-      buf = (char *) xmalloc (strlen (s) + 2);
+      buf = xmalloc (strlen (s) + 2);
       sprintf (buf, "%c%s", mod, s);
       free (s);
-      if (! stab_push_string (info, buf, 0, definition, size))
-       return false;
-      free (buf);
+      return stab_push_string (info, buf, 0, definition, size);
     }
   else
     {
@@ -887,9 +901,9 @@ stab_modify_type (struct stab_write_handle *info, int mod,
            alloc = 10;
          while ((size_t) targindex >= alloc)
            alloc *= 2;
-         *cache = (long *) xrealloc (*cache, alloc * sizeof (long));
+         *cache = xrealloc (*cache, alloc * sizeof (**cache));
          memset (*cache + *cache_alloc, 0,
-                 (alloc - *cache_alloc) * sizeof (long));
+                 (alloc - *cache_alloc) * sizeof (**cache));
          *cache_alloc = alloc;
        }
 
@@ -903,8 +917,7 @@ stab_modify_type (struct stab_write_handle *info, int mod,
              is a struct which we did not define at the time it was
              referenced).  */
          free (stab_pop_type (info));
-         if (! stab_push_defined_type (info, tindex, size))
-           return false;
+         return stab_push_defined_type (info, tindex, size);
        }
       else
        {
@@ -912,20 +925,15 @@ stab_modify_type (struct stab_write_handle *info, int mod,
          ++info->type_index;
 
          s = stab_pop_type (info);
-         buf = (char *) xmalloc (strlen (s) + 20);
+         buf = xmalloc (strlen (s) + 23);
          sprintf (buf, "%ld=%c%s", tindex, mod, s);
          free (s);
 
          (*cache)[targindex] = tindex;
 
-         if (! stab_push_string (info, buf, tindex, true, size))
-           return false;
-
-         free (buf);
+         return stab_push_string (info, buf, tindex, true, size);
        }
     }
-
-  return true;
 }
 
 /* Push a pointer type.  */
@@ -962,14 +970,11 @@ stab_function_type (void *p, int argcount,
 
          s = stab_pop_type (info);
 
-         buf = (char *) xmalloc (strlen (s) + 3);
+         buf = xmalloc (strlen (s) + 3);
          sprintf (buf, ":t%s", s);
          free (s);
 
-         if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
-           return false;
-
-         free (buf);
+         return stab_write_symbol_and_free (info, N_LSYM, 0, 0, buf);
        }
     }
 
@@ -1003,16 +1008,11 @@ stab_range_type (void *p, bfd_signed_vma low, bfd_signed_vma high)
   size = info->type_stack->size;
 
   s = stab_pop_type (info);
-  buf = (char *) xmalloc (strlen (s) + 100);
+  buf = xmalloc (strlen (s) + 45);
   sprintf (buf, "r%s;%ld;%ld;", s, (long) low, (long) high);
   free (s);
 
-  if (! stab_push_string (info, buf, 0, definition, size))
-    return false;
-
-  free (buf);
-
-  return true;
+  return stab_push_string (info, buf, 0, definition, size);
 }
 
 /* Push an array type.  */
@@ -1035,7 +1035,7 @@ stab_array_type (void *p, bfd_signed_vma low, bfd_signed_vma high,
   element_size = info->type_stack->size;
   element = stab_pop_type (info);
 
-  buf = (char *) xmalloc (strlen (range) + strlen (element) + 100);
+  buf = xmalloc (strlen (range) + strlen (element) + 70);
 
   if (! stringp)
     {
@@ -1061,12 +1061,7 @@ stab_array_type (void *p, bfd_signed_vma low, bfd_signed_vma high,
     size = 0;
   else
     size = element_size * ((high - low) + 1);
-  if (! stab_push_string (info, buf, tindex, definition, size))
-    return false;
-
-  free (buf);
-
-  return true;
+  return stab_push_string (info, buf, tindex, definition, size);
 }
 
 /* Push a set type.  */
@@ -1082,7 +1077,7 @@ stab_set_type (void *p, bool bitstringp)
   definition = info->type_stack->definition;
 
   s = stab_pop_type (info);
-  buf = (char *) xmalloc (strlen (s) + 30);
+  buf = xmalloc (strlen (s) + 26);
 
   if (! bitstringp)
     {
@@ -1102,12 +1097,7 @@ stab_set_type (void *p, bool bitstringp)
   sprintf (buf + strlen (buf), "S%s", s);
   free (s);
 
-  if (! stab_push_string (info, buf, tindex, definition, 0))
-    return false;
-
-  free (buf);
-
-  return true;
+  return stab_push_string (info, buf, tindex, definition, 0);
 }
 
 /* Push an offset type.  */
@@ -1125,17 +1115,12 @@ stab_offset_type (void *p)
   definition = definition || info->type_stack->definition;
   base = stab_pop_type (info);
 
-  buf = (char *) xmalloc (strlen (target) + strlen (base) + 3);
+  buf = xmalloc (strlen (target) + strlen (base) + 3);
   sprintf (buf, "@%s,%s", base, target);
   free (base);
   free (target);
 
-  if (! stab_push_string (info, buf, 0, definition, 0))
-    return false;
-
-  free (buf);
-
-  return true;
+  return stab_push_string (info, buf, 0, definition, 0);
 }
 
 /* Push a method type.  */
@@ -1180,9 +1165,12 @@ stab_method_type (void *p, bool domainp, int argcount,
        args = NULL;
       else
        {
-         args = (char **) xmalloc (1 * sizeof (*args));
+         args = xmalloc (1 * sizeof (*args));
          if (! stab_empty_type (p))
-           return false;
+           {
+             free (args);
+             return false;
+           }
          definition = definition || info->type_stack->definition;
          args[0] = stab_pop_type (info);
          argcount = 1;
@@ -1190,7 +1178,7 @@ stab_method_type (void *p, bool domainp, int argcount,
     }
   else
     {
-      args = (char **) xmalloc ((argcount + 1) * sizeof (*args));
+      args = xmalloc ((argcount + 1) * sizeof (*args));
       for (i = argcount - 1; i >= 0; i--)
        {
          definition = definition || info->type_stack->definition;
@@ -1199,7 +1187,12 @@ stab_method_type (void *p, bool domainp, int argcount,
       if (! varargs)
        {
          if (! stab_empty_type (p))
-           return false;
+           {
+             for (i = 0; i < argcount; i++)
+               free (args[i]);
+             free (args);
+             return false;
+           }
          definition = definition || info->type_stack->definition;
          args[argcount] = stab_pop_type (info);
          ++argcount;
@@ -1209,11 +1202,11 @@ stab_method_type (void *p, bool domainp, int argcount,
   definition = definition || info->type_stack->definition;
   return_type = stab_pop_type (info);
 
-  len = strlen (domain) + strlen (return_type) + 10;
+  len = strlen (domain) + strlen (return_type) + 4 + argcount;
   for (i = 0; i < argcount; i++)
     len += strlen (args[i]);
 
-  buf = (char *) xmalloc (len);
+  buf = xmalloc (len);
 
   sprintf (buf, "#%s,%s", domain, return_type);
   free (domain);
@@ -1228,12 +1221,7 @@ stab_method_type (void *p, bool domainp, int argcount,
 
   free (args);
 
-  if (! stab_push_string (info, buf, 0, definition, 0))
-    return false;
-
-  free (buf);
-
-  return true;
+  return stab_push_string (info, buf, 0, definition, 0);
 }
 
 /* Push a const version of a type.  */
@@ -1276,13 +1264,13 @@ stab_get_struct_index (struct stab_write_handle *info, const char *tag,
       while (id >= alloc)
        alloc *= 2;
       info->type_cache.struct_types =
-       (struct stab_tag *) xrealloc (info->type_cache.struct_types,
-                                     alloc * sizeof (struct stab_tag));
+       xrealloc (info->type_cache.struct_types,
+                 alloc * sizeof (*info->type_cache.struct_types));
       memset ((info->type_cache.struct_types
               + info->type_cache.struct_types_alloc),
              0,
              ((alloc - info->type_cache.struct_types_alloc)
-              * sizeof (struct stab_tag)));
+              * sizeof (*info->type_cache.struct_types)));
       info->type_cache.struct_types_alloc = alloc;
     }
 
@@ -1338,10 +1326,10 @@ stab_start_struct_type (void *p, const char *tag, unsigned int id,
           structp ? 's' : 'u',
           size);
 
-  if (! stab_push_string (info, buf, tindex, definition, size))
+  if (!stab_push_string_dup (info, buf, tindex, definition, size))
     return false;
 
-  info->type_stack->fields = (char *) xmalloc (1);
+  info->type_stack->fields = xmalloc (1);
   info->type_stack->fields[0] = '\0';
 
   return true;
@@ -1366,12 +1354,13 @@ stab_struct_field (void *p, const char *name, bfd_vma bitpos,
   /* Add this field to the end of the current struct fields, which is
      currently on the top of the stack.  */
   if (info->type_stack->fields == NULL)
-    return false;
+    {
+      free (s);
+      return false;
+    }
 
-  n = (char *) xmalloc (strlen (info->type_stack->fields)
-                       + strlen (name)
-                       + strlen (s)
-                       + 50);
+  n = xmalloc (strlen (info->type_stack->fields)
+              + strlen (name) + strlen (s) + 50);
 
   switch (visibility)
     {
@@ -1403,6 +1392,7 @@ stab_struct_field (void *p, const char *name, bfd_vma bitpos,
           (long) bitpos, (long) bitsize);
 
   free (info->type_stack->fields);
+  free (s);
   info->type_stack->fields = n;
 
   if (definition)
@@ -1431,17 +1421,12 @@ stab_end_struct_type (void *p)
   fields = info->type_stack->fields;
   first = stab_pop_type (info);
 
-  buf = (char *) xmalloc (strlen (first) + strlen (fields) + 2);
+  buf = xmalloc (strlen (first) + strlen (fields) + 2);
   sprintf (buf, "%s%s;", first, fields);
   free (first);
   free (fields);
 
-  if (! stab_push_string (info, buf, tindex, definition, size))
-    return false;
-
-  free (buf);
-
-  return true;
+  return stab_push_string (info, buf, tindex, definition, size);
 }
 
 /* Start outputting a class.  */
@@ -1462,7 +1447,10 @@ stab_start_class_type (void *p, const char *tag, unsigned int id,
     }
 
   if (! stab_start_struct_type (p, tag, id, structp, size))
-    return false;
+    {
+      free (vstring);
+      return false;
+    }
 
   if (vptr)
     {
@@ -1472,14 +1460,14 @@ stab_start_class_type (void *p, const char *tag, unsigned int id,
        {
          if (info->type_stack->index < 1)
            return false;
-         vtable = (char *) xmalloc (20);
+         vtable = xmalloc (23);
          sprintf (vtable, "~%%%ld", info->type_stack->index);
        }
       else
        {
          if (vstring == NULL)
            return false;
-         vtable = (char *) xmalloc (strlen (vstring) + 3);
+         vtable = xmalloc (strlen (vstring) + 3);
          sprintf (vtable, "~%%%s", vstring);
          free (vstring);
          if (definition)
@@ -1510,11 +1498,8 @@ stab_class_static_member (void *p, const char *name, const char *physname,
 
   if (info->type_stack->fields == NULL)
     return false;
-  n = (char *) xmalloc (strlen (info->type_stack->fields)
-                       + strlen (name)
-                       + strlen (s)
-                       + strlen (physname)
-                       + 10);
+  n = xmalloc (strlen (info->type_stack->fields) + strlen (name)
+              + strlen (s) + strlen (physname) + 10);
 
   switch (visibility)
     {
@@ -1537,6 +1522,7 @@ stab_class_static_member (void *p, const char *name, const char *physname,
   sprintf (n, "%s%s:%s%s:%s;", info->type_stack->fields, name, vis, s,
           physname);
 
+  free (s);
   free (info->type_stack->fields);
   info->type_stack->fields = n;
 
@@ -1564,7 +1550,7 @@ stab_class_baseclass (void *p, bfd_vma bitpos, bool is_virtual,
 
   /* Build the base class specifier.  */
 
-  buf = (char *) xmalloc (strlen (s) + 25);
+  buf = xmalloc (strlen (s) + 25);
   buf[0] = is_virtual ? '1' : '0';
   switch (visibility)
     {
@@ -1590,7 +1576,10 @@ stab_class_baseclass (void *p, bfd_vma bitpos, bool is_virtual,
   /* Add the new baseclass to the existing ones.  */
 
   if (info->type_stack == NULL || info->type_stack->fields == NULL)
-    return false;
+    {
+      free (buf);
+      return false;
+    }
 
   if (info->type_stack->baseclasses == NULL)
     c = 0;
@@ -1601,8 +1590,8 @@ stab_class_baseclass (void *p, bfd_vma bitpos, bool is_virtual,
        ++c;
     }
 
-  baseclasses = (char **) xrealloc (info->type_stack->baseclasses,
-                                   (c + 2) * sizeof (*baseclasses));
+  baseclasses = xrealloc (info->type_stack->baseclasses,
+                         (c + 2) * sizeof (*baseclasses));
   baseclasses[c] = buf;
   baseclasses[c + 1] = NULL;
 
@@ -1627,16 +1616,12 @@ stab_class_start_method (void *p, const char *name)
 
   if (info->type_stack->methods == NULL)
     {
-      m = (char *) xmalloc (strlen (name) + 3);
+      m = xmalloc (strlen (name) + 3);
       *m = '\0';
     }
   else
-    {
-      m = (char *) xrealloc (info->type_stack->methods,
-                            (strlen (info->type_stack->methods)
-                             + strlen (name)
-                             + 4));
-    }
+    m = xrealloc (info->type_stack->methods,
+                 strlen (info->type_stack->methods) + strlen (name) + 3);
 
   sprintf (m + strlen (m), "%s::", name);
 
@@ -1669,7 +1654,11 @@ stab_class_method_var (struct stab_write_handle *info, const char *physname,
     }
 
   if (info->type_stack == NULL || info->type_stack->methods == NULL)
-    return false;
+    {
+      free (type);
+      free (context);
+      return false;
+    }
 
   switch (visibility)
     {
@@ -1712,12 +1701,9 @@ stab_class_method_var (struct stab_write_handle *info, const char *physname,
     typec = '*';
 
   info->type_stack->methods =
-    (char *) xrealloc (info->type_stack->methods,
-                      (strlen (info->type_stack->methods)
-                       + strlen (type)
-                       + strlen (physname)
-                       + (contextp ? strlen (context) : 0)
-                       + 40));
+    xrealloc (info->type_stack->methods,
+             (strlen (info->type_stack->methods) + strlen (type)
+              + strlen (physname) + (contextp ? strlen (context) : 0) + 40));
 
   sprintf (info->type_stack->methods + strlen (info->type_stack->methods),
           "%s:%s;%c%c%c", type, physname, visc, qualc, typec);
@@ -1813,7 +1799,7 @@ stab_end_class_type (void *p)
 
   /* Build the class definition.  */
 
-  buf = (char *) xmalloc (len);
+  buf = xmalloc (len);
 
   strcpy (buf, info->type_stack->string);
 
@@ -1904,7 +1890,7 @@ stab_typdef (void *p, const char *name)
   size = info->type_stack->size;
   s = stab_pop_type (info);
 
-  buf = (char *) xmalloc (strlen (name) + strlen (s) + 20);
+  buf = xmalloc (strlen (name) + strlen (s) + 20);
 
   if (tindex > 0)
     sprintf (buf, "%s:t%s", name, s);
@@ -1917,11 +1903,9 @@ stab_typdef (void *p, const char *name)
 
   free (s);
 
-  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
+  if (!stab_write_symbol_and_free (info, N_LSYM, 0, 0, buf))
     return false;
 
-  free (buf);
-
   h = string_hash_lookup (&info->typedef_hash, name, true, false);
   if (h == NULL)
     {
@@ -1948,17 +1932,12 @@ stab_tag (void *p, const char *tag)
 
   s = stab_pop_type (info);
 
-  buf = (char *) xmalloc (strlen (tag) + strlen (s) + 3);
+  buf = xmalloc (strlen (tag) + strlen (s) + 3);
 
   sprintf (buf, "%s:T%s", tag, s);
   free (s);
 
-  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
-    return false;
-
-  free (buf);
-
-  return true;
+  return stab_write_symbol_and_free (info, N_LSYM, 0, 0, buf);
 }
 
 /* Define an integer constant.  */
@@ -1969,15 +1948,10 @@ stab_int_constant (void *p, const char *name, bfd_vma val)
   struct stab_write_handle *info = (struct stab_write_handle *) p;
   char *buf;
 
-  buf = (char *) xmalloc (strlen (name) + 20);
+  buf = xmalloc (strlen (name) + 20);
   sprintf (buf, "%s:c=i%ld", name, (long) val);
 
-  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
-    return false;
-
-  free (buf);
-
-  return true;
+  return stab_write_symbol_and_free (info, N_LSYM, 0, 0, buf);
 }
 
 /* Define a floating point constant.  */
@@ -1988,15 +1962,10 @@ stab_float_constant (void *p, const char *name, double val)
   struct stab_write_handle *info = (struct stab_write_handle *) p;
   char *buf;
 
-  buf = (char *) xmalloc (strlen (name) + 20);
+  buf = xmalloc (strlen (name) + 20);
   sprintf (buf, "%s:c=f%g", name, val);
 
-  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
-    return false;
-
-  free (buf);
-
-  return true;
+  return stab_write_symbol_and_free (info, N_LSYM, 0, 0, buf);
 }
 
 /* Define a typed constant.  */
@@ -2009,16 +1978,11 @@ stab_typed_constant (void *p, const char *name, bfd_vma val)
 
   s = stab_pop_type (info);
 
-  buf = (char *) xmalloc (strlen (name) + strlen (s) + 20);
+  buf = xmalloc (strlen (name) + strlen (s) + 20);
   sprintf (buf, "%s:c=e%s,%ld", name, s, (long) val);
   free (s);
 
-  if (! stab_write_symbol (info, N_LSYM, 0, 0, buf))
-    return false;
-
-  free (buf);
-
-  return true;
+  return stab_write_symbol_and_free (info, N_LSYM, 0, 0, buf);
 }
 
 /* Record a variable.  */
@@ -2066,7 +2030,7 @@ stab_variable (void *p, const char *name, enum debug_var_kind kind,
 
          tindex = info->type_index;
          ++info->type_index;
-         n = (char *) xmalloc (strlen (s) + 20);
+         n = xmalloc (strlen (s) + 20);
          sprintf (n, "%ld=%s", tindex, s);
          free (s);
          s = n;
@@ -2079,16 +2043,11 @@ stab_variable (void *p, const char *name, enum debug_var_kind kind,
       break;
     }
 
-  buf = (char *) xmalloc (strlen (name) + strlen (s) + 3);
+  buf = xmalloc (strlen (name) + strlen (s) + 3);
   sprintf (buf, "%s:%s%s", name, kindstr, s);
   free (s);
 
-  if (! stab_write_symbol (info, stab_type, 0, val, buf))
-    return false;
-
-  free (buf);
-
-  return true;
+  return stab_write_symbol_and_free (info, stab_type, 0, val, buf);
 }
 
 /* Start outputting a function.  */
@@ -2104,20 +2063,16 @@ stab_start_function (void *p, const char *name, bool globalp)
 
   rettype = stab_pop_type (info);
 
-  buf = (char *) xmalloc (strlen (name) + strlen (rettype) + 3);
+  buf = xmalloc (strlen (name) + strlen (rettype) + 3);
   sprintf (buf, "%s:%c%s", name,
           globalp ? 'F' : 'f',
           rettype);
+  free (rettype);
 
   /* We don't know the value now, so we set it in start_block.  */
   info->fun_offset = info->symbols_size;
 
-  if (! stab_write_symbol (info, N_FUN, 0, 0, buf))
-    return false;
-
-  free (buf);
-
-  return true;
+  return stab_write_symbol_and_free (info, N_FUN, 0, 0, buf);
 }
 
 /* Output a function parameter.  */
@@ -2158,16 +2113,11 @@ stab_function_parameter (void *p, const char *name, enum debug_parm_kind kind, b
       break;
     }
 
-  buf = (char *) xmalloc (strlen (name) + strlen (s) + 3);
+  buf = xmalloc (strlen (name) + strlen (s) + 3);
   sprintf (buf, "%s:%c%s", name, kindc, s);
   free (s);
 
-  if (! stab_write_symbol (info, stab_type, 0, val, buf))
-    return false;
-
-  free (buf);
-
-  return true;
+  return stab_write_symbol_and_free (info, stab_type, 0, val, buf);
 }
 
 /* Start a block.  */