gas macro memory leaks
authorAlan Modra <amodra@gmail.com>
Fri, 27 Jan 2023 00:01:56 +0000 (10:31 +1030)
committerAlan Modra <amodra@gmail.com>
Fri, 27 Jan 2023 05:08:52 +0000 (15:38 +1030)
This tidies memory allocated for entries in macro_hash.  Freeing the
macro name requires a little restructuring of the define_macro
interface due to the name being used in the error message, and exposed
the fact that the name and other fields were not initialised by the
iq2000 backend.

There is also a fix for
 .macro .macro
 .endm
 .macro .macro
 .endm
which prior to this patch reported
mac.s:1: Warning: attempt to redefine pseudo-op `.macro' ignored
mac.s:3: Error: Macro `.macro' was already defined
rather than reporting the attempt to redefine twice.

* macro.c (macro_del_f): New function.
(macro_init): Use it when creating macro_hash.
(free_macro): Free macro name too.
(define_macro): Return the macro_entry, remove idx, file, line and
namep params.  Call as_where.  Report errors here.  Delete macro
from macro_hash on attempt to redefined pseudo-op.
(delete_macro): Don't call free_macro.
* macro.h (define_macro): Update prototype.
* read.c (s_macro): Adjust to suit.
* config/tc-iq2000.c (iq2000_add_macro): Init all fields of
macro_entry.

gas/config/tc-iq2000.c
gas/macro.c
gas/macro.h
gas/read.c

index f5d7c90d0d7a7299b00f78b481aa611f5d4bf7e4..4e169727b840723ff65ecb5a11b5646a0c679e6f 100644 (file)
@@ -229,15 +229,14 @@ iq2000_add_macro (const char *  name,
                  const char ** arguments)
 {
   macro_entry *macro;
-  sb macro_name;
-  const char *namestr;
 
   macro = XNEW (macro_entry);
+  macro->name = xstrdup (name);
   sb_new (& macro->sub);
-  sb_new (& macro_name);
-
   macro->formal_count = 0;
   macro->formals = 0;
+  macro->formal_hash = str_htab_create ();
+  macro->file = as_where (&macro->line);
 
   sb_add_string (& macro->sub, semantics);
 
@@ -245,9 +244,6 @@ iq2000_add_macro (const char *  name,
     {
       formal_entry ** p = &macro->formals;
 
-      macro->formal_count = 0;
-      macro->formal_hash = str_htab_create ();
-
       while (*arguments != NULL)
        {
          formal_entry *formal;
@@ -261,7 +257,7 @@ iq2000_add_macro (const char *  name,
          /* chlm: Added the following to allow defaulted args.  */
          if (strchr (*arguments,'='))
            {
-             char * tt_args = strdup (*arguments);
+             char * tt_args = xstrdup (*arguments);
              char * tt_dflt = strchr (tt_args,'=');
 
              *tt_dflt = 0;
@@ -283,9 +279,7 @@ iq2000_add_macro (const char *  name,
        }
     }
 
-  sb_add_string (&macro_name, name);
-  namestr = sb_terminate (&macro_name);
-  str_hash_insert (macro_hash, namestr, macro, 1);
+  str_hash_insert (macro_hash, macro->name, macro, 1);
 
   macro_defined = 1;
 }
index ed1e9ef605aaa104669b9c35d4cb646e7b9f6375..763bafbdc3dad99e50e0a594dd028389c202d9fd 100644 (file)
@@ -70,13 +70,23 @@ static size_t (*macro_expr) (const char *, size_t, sb *, offsetT *);
 
 static int macro_number;
 
+static void free_macro (macro_entry *);
+
+static void
+macro_del_f (void *ent)
+{
+  string_tuple_t *tuple = ent;
+  free_macro ((macro_entry *) tuple->value);
+}
+
 /* Initialize macro processing.  */
 
 void
 macro_init (int alternate, int mri, int strip_at,
            size_t (*exp) (const char *, size_t, sb *, offsetT *))
 {
-  macro_hash = str_htab_create ();
+  macro_hash = htab_create_alloc (16, hash_string_tuple, eq_string_tuple,
+                                 macro_del_f, notes_calloc, NULL);
   macro_defined = 0;
   macro_alternate = alternate;
   macro_mri = mri;
@@ -664,34 +674,30 @@ free_macro (macro_entry *macro)
     }
   htab_delete (macro->formal_hash);
   sb_kill (&macro->sub);
+  free ((char *) macro->name);
   free (macro);
 }
 
-/* Define a new macro.  Returns NULL on success, otherwise returns an
-   error message.  If NAMEP is not NULL, *NAMEP is set to the name of
-   the macro which was defined.  */
+/* Define a new macro.  */
 
-const char *
-define_macro (size_t idx, sb *in, sb *label,
-             size_t (*get_line) (sb *),
-             const char *file, unsigned int line,
-             const char **namep)
+macro_entry *
+define_macro (sb *in, sb *label, size_t (*get_line) (sb *))
 {
   macro_entry *macro;
   sb name;
+  size_t idx;
   const char *error = NULL;
 
   macro = XNEW (macro_entry);
   sb_new (&macro->sub);
   sb_new (&name);
-  macro->file = file;
-  macro->line = line;
+  macro->file = as_where (&macro->line);
 
   macro->formal_count = 0;
   macro->formals = 0;
   macro->formal_hash = str_htab_create ();
 
-  idx = sb_skip_white (idx, in);
+  idx = sb_skip_white (0, in);
   if (! buffer_and_nest ("MACRO", "ENDM", &macro->sub, get_line))
     error = _("unexpected end of file in macro `%s' definition");
   if (label != NULL && label->len != 0)
@@ -740,15 +746,16 @@ define_macro (size_t idx, sb *in, sb *label,
        error = _("Macro `%s' was already defined");
     }
 
-  if (namep != NULL)
-    *namep = macro->name;
-
   if (!error)
     macro_defined = 1;
   else
-    free_macro (macro);
+    {
+      as_bad_where (macro->file, macro->line, error, macro->name);
+      free_macro (macro);
+      macro = NULL;
+    }
 
-  return error;
+  return macro;
 }
 
 /* Scan a token, and then skip KIND.  */
@@ -1318,10 +1325,7 @@ delete_macro (const char *name)
 
   macro = str_hash_find (macro_hash, copy);
   if (macro != NULL)
-    {
-      free_macro (macro);
-      str_hash_delete (macro_hash, copy);
-    }
+    str_hash_delete (macro_hash, copy);
   else
     as_warn (_("Attempt to purge non-existing macro `%s'"), copy);
   free (copy);
index 5593281c552c84ae360d644ac98f0d1121dc3e93..2ec0ec451d5451fe72b42c261aee06b307a4f558 100644 (file)
@@ -88,8 +88,7 @@ extern void macro_init (int, int, int,
 extern void macro_end (void);
 extern void macro_set_alternate (int);
 extern void macro_mri_mode (int);
-extern const char *define_macro (size_t, sb *, sb *, size_t (*) (sb *),
-                                const char *, unsigned int, const char **);
+extern macro_entry *define_macro (sb *, sb *, size_t (*) (sb *));
 extern int check_macro (const char *, sb *, const char **, macro_entry **);
 extern void delete_macro (const char *);
 extern const char *expand_irp (int, size_t, sb *, sb *, size_t (*) (sb *));
index 8fb11e8a67cb352be819482900cc9cec16e17279..c5a477f9e08c7ece81ee5fdcd0175146f198e3eb 100644 (file)
@@ -2647,13 +2647,8 @@ void
 s_macro (int ignore ATTRIBUTE_UNUSED)
 {
   char *eol;
-  const char * file;
-  unsigned int line;
   sb s;
-  const char *err;
-  const char *name;
-
-  file = as_where (&line);
+  macro_entry *macro;
 
   eol = find_end_of_line (input_line_pointer, 0);
   sb_build (&s, eol - input_line_pointer);
@@ -2664,19 +2659,18 @@ s_macro (int ignore ATTRIBUTE_UNUSED)
     {
       sb label;
       size_t len;
+      const char *name;
 
       name = S_GET_NAME (line_label);
       len = strlen (name);
       sb_build (&label, len);
       sb_add_buffer (&label, name, len);
-      err = define_macro (0, &s, &label, get_macro_line_sb, file, line, &name);
+      macro = define_macro (&s, &label, get_macro_line_sb);
       sb_kill (&label);
     }
   else
-    err = define_macro (0, &s, NULL, get_macro_line_sb, file, line, &name);
-  if (err != NULL)
-    as_bad_where (file, line, err, name);
-  else
+    macro = define_macro (&s, NULL, get_macro_line_sb);
+  if (macro != NULL)
     {
       if (line_label != NULL)
        {
@@ -2686,14 +2680,16 @@ s_macro (int ignore ATTRIBUTE_UNUSED)
        }
 
       if (((NO_PSEUDO_DOT || flag_m68k_mri)
-          && str_hash_find (po_hash, name) != NULL)
+          && str_hash_find (po_hash, macro->name) != NULL)
          || (!flag_m68k_mri
-             && *name == '.'
-             && str_hash_find (po_hash, name + 1) != NULL))
-       as_warn_where (file,
-                line,
-                _("attempt to redefine pseudo-op `%s' ignored"),
-                name);
+             && macro->name[0] == '.'
+             && str_hash_find (po_hash, macro->name + 1) != NULL))
+       {
+         as_warn_where (macro->file, macro->line,
+                        _("attempt to redefine pseudo-op `%s' ignored"),
+                        macro->name);
+         str_hash_delete (macro_hash, macro->name);
+       }
     }
 
   sb_kill (&s);