diff mbox

[libiberty] Remove malloc/realloc from demangler (was: Add a couple of missing casts)

Message ID 20131220130010.GA10338@blade.nx
State New
Headers show

Commit Message

Gary Benson Dec. 20, 2013, 1 p.m. UTC
Ian Lance Taylor wrote:
> On Wed, Nov 13, 2013 at 7:30 AM, Gary Benson <gbenson@redhat.com> wrote:
> > Richard Biener wrote:
> > > On Tue, Nov 12, 2013 at 8:55 PM, Ian Lance Taylor <iant@google.com> wrote:
> > > > On Tue, Nov 12, 2013 at 11:24 AM, Uros Bizjak <ubizjak@gmail.com> wrote:
> > > > >
> > > > > This was uncovered by x86 lto-profiledbootstrap. The patch allows
> > > > > lto-profiledbootstrap to proceed further.
> > > > >
> > > > > 2013-11-12  Uros Bizjak  <ubizjak@gmail.com>
> > > > >
> > > > >     * cp-demangle.c (d_copy_templates): Cast result of malloc
> > > > >     to (struct d_print_template *).
> > > > >     (d_print_comp): Cast result of realloc to (struct d_saved scope *).
> > > > >
> > > > > Tested on x86_64-pc-linux-gnu.
> > > > >
> > > > > OK for mainline?
> > > >
> > > > The patch is OK, but this code is troubling.  I obviously
> > > > should have looked at it earlier.  The C++ demangler is
> > > > sometimes used in panic situations, when malloc is not
> > > > available.  The interface was designed to be usable without
> > > > requiring malloc, by passing in a sufficiently large buffer.
> > > > I'm concerned that we apparently now require malloc to work.
> > >
> > > That indeed looks like an important regression - Gary, can you
> > > please work to fix this?
> >
> > I'm on it.
> 
> Thanks.  See also the cplus_demangle_print_callback function.

The below patch should remedy this.

After the end of today I'll likely not check this email until
January 5.  If this patch gets approved before then and you
want it in please either ping me on gary@ the domain in my sig
or just somebody else commit it for me.

Thanks,
Gary

Comments

Ian Lance Taylor Dec. 20, 2013, 2:30 p.m. UTC | #1
On Fri, Dec 20, 2013 at 5:00 AM, Gary Benson <gbenson@redhat.com> wrote:
>
> --- a/libiberty/ChangeLog
> +++ b/libiberty/ChangeLog
> @@ -1,3 +1,20 @@
> +2013-12-20  Gary Benson  <gbenson@redhat.com>
> +
> +       * cp-demangle.c (struct d_print_info): New fields
> +       next_saved_scope, copy_templates, next_copy_template and
> +       num_copy_templates.
> +       (d_count_templates): New function.
> +       (d_print_init): New parameter "dc".
> +       Estimate numbers of templates and scopes required.
> +       (d_print_free): Removed function.
> +       (cplus_demangle_print_callback): Allocate stack for
> +       templates and scopes.  Removed call to d_print_free.
> +       (d_copy_templates): Removed function.
> +       (d_save_scope): New function.
> +       (d_get_saved_scope): Likewise.
> +       (d_print_comp): Replace state saving/restoring code with
> +       calls to d_save_scope and d_get_saved_scope.

This is OK.

Thanks for following up on this.

Ian
diff mbox

Patch

diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 825ddd2..78c1433 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,20 @@ 
+2013-12-20  Gary Benson  <gbenson@redhat.com>
+
+	* cp-demangle.c (struct d_print_info): New fields
+	next_saved_scope, copy_templates, next_copy_template and
+	num_copy_templates.
+	(d_count_templates): New function.
+	(d_print_init): New parameter "dc".
+	Estimate numbers of templates and scopes required.
+	(d_print_free): Removed function.
+	(cplus_demangle_print_callback): Allocate stack for
+	templates and scopes.  Removed call to d_print_free.
+	(d_copy_templates): Removed function.
+	(d_save_scope): New function.
+	(d_get_saved_scope): Likewise.
+	(d_print_comp): Replace state saving/restoring code with
+	calls to d_save_scope and d_get_saved_scope.
+
 2013-11-22  Cary Coutant  <ccoutant@google.com>
     
 	PR other/59195
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 029151e..de08d94 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -329,8 +329,16 @@  struct d_print_info
   unsigned long int flush_count;
   /* Array of saved scopes for evaluating substitutions.  */
   struct d_saved_scope *saved_scopes;
+  /* Index of the next unused saved scope in the above array.  */
+  int next_saved_scope;
   /* Number of saved scopes in the above array.  */
   int num_saved_scopes;
+  /* Array of templates for saving into scopes.  */
+  struct d_print_template *copy_templates;
+  /* Index of the next unused copy template in the above array.  */
+  int next_copy_template;
+  /* Number of copy templates in the above array.  */
+  int num_copy_templates;
   /* The nearest enclosing template, if any.  */
   const struct demangle_component *current_template;
 };
@@ -475,7 +483,8 @@  static void
 d_growable_string_callback_adapter (const char *, size_t, void *);
 
 static void
-d_print_init (struct d_print_info *, demangle_callbackref, void *);
+d_print_init (struct d_print_info *, demangle_callbackref, void *,
+	      const struct demangle_component *);
 
 static inline void d_print_error (struct d_print_info *);
 
@@ -3770,11 +3779,141 @@  d_growable_string_callback_adapter (const char *s, size_t l, void *opaque)
   d_growable_string_append_buffer (dgs, s, l);
 }
 
+/* Walk the tree, counting the number of templates encountered, and
+   the number of times a scope might be saved.  These counts will be
+   used to allocate data structures for d_print_comp, so the logic
+   here must mirror the logic d_print_comp will use.  It is not
+   important that the resulting numbers are exact, so long as they
+   are larger than the actual numbers encountered.  */
+
+static void
+d_count_templates_scopes (int *num_templates, int *num_scopes,
+			  const struct demangle_component *dc)
+{
+  if (dc == NULL)
+    return;
+
+  switch (dc->type)
+    {
+    case DEMANGLE_COMPONENT_NAME:
+    case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
+    case DEMANGLE_COMPONENT_FUNCTION_PARAM:
+    case DEMANGLE_COMPONENT_SUB_STD:
+    case DEMANGLE_COMPONENT_BUILTIN_TYPE:
+    case DEMANGLE_COMPONENT_OPERATOR:
+    case DEMANGLE_COMPONENT_CHARACTER:
+    case DEMANGLE_COMPONENT_NUMBER:
+    case DEMANGLE_COMPONENT_UNNAMED_TYPE:
+      break;
+
+    case DEMANGLE_COMPONENT_TEMPLATE:
+      (*num_templates)++;
+      goto recurse_left_right;
+
+    case DEMANGLE_COMPONENT_REFERENCE:
+    case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
+      if (d_left (dc)->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
+	(*num_scopes)++;
+      goto recurse_left_right;
+
+    case DEMANGLE_COMPONENT_QUAL_NAME:
+    case DEMANGLE_COMPONENT_LOCAL_NAME:
+    case DEMANGLE_COMPONENT_TYPED_NAME:
+    case DEMANGLE_COMPONENT_VTABLE:
+    case DEMANGLE_COMPONENT_VTT:
+    case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
+    case DEMANGLE_COMPONENT_TYPEINFO:
+    case DEMANGLE_COMPONENT_TYPEINFO_NAME:
+    case DEMANGLE_COMPONENT_TYPEINFO_FN:
+    case DEMANGLE_COMPONENT_THUNK:
+    case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
+    case DEMANGLE_COMPONENT_COVARIANT_THUNK:
+    case DEMANGLE_COMPONENT_JAVA_CLASS:
+    case DEMANGLE_COMPONENT_GUARD:
+    case DEMANGLE_COMPONENT_TLS_INIT:
+    case DEMANGLE_COMPONENT_TLS_WRAPPER:
+    case DEMANGLE_COMPONENT_REFTEMP:
+    case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
+    case DEMANGLE_COMPONENT_RESTRICT:
+    case DEMANGLE_COMPONENT_VOLATILE:
+    case DEMANGLE_COMPONENT_CONST:
+    case DEMANGLE_COMPONENT_RESTRICT_THIS:
+    case DEMANGLE_COMPONENT_VOLATILE_THIS:
+    case DEMANGLE_COMPONENT_CONST_THIS:
+    case DEMANGLE_COMPONENT_REFERENCE_THIS:
+    case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+    case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+    case DEMANGLE_COMPONENT_POINTER:
+    case DEMANGLE_COMPONENT_COMPLEX:
+    case DEMANGLE_COMPONENT_IMAGINARY:
+    case DEMANGLE_COMPONENT_VENDOR_TYPE:
+    case DEMANGLE_COMPONENT_FUNCTION_TYPE:
+    case DEMANGLE_COMPONENT_ARRAY_TYPE:
+    case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+    case DEMANGLE_COMPONENT_FIXED_TYPE:
+    case DEMANGLE_COMPONENT_VECTOR_TYPE:
+    case DEMANGLE_COMPONENT_ARGLIST:
+    case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
+    case DEMANGLE_COMPONENT_INITIALIZER_LIST:
+    case DEMANGLE_COMPONENT_CAST:
+    case DEMANGLE_COMPONENT_NULLARY:
+    case DEMANGLE_COMPONENT_UNARY:
+    case DEMANGLE_COMPONENT_BINARY:
+    case DEMANGLE_COMPONENT_BINARY_ARGS:
+    case DEMANGLE_COMPONENT_TRINARY:
+    case DEMANGLE_COMPONENT_TRINARY_ARG1:
+    case DEMANGLE_COMPONENT_TRINARY_ARG2:
+    case DEMANGLE_COMPONENT_LITERAL:
+    case DEMANGLE_COMPONENT_LITERAL_NEG:
+    case DEMANGLE_COMPONENT_JAVA_RESOURCE:
+    case DEMANGLE_COMPONENT_COMPOUND_NAME:
+    case DEMANGLE_COMPONENT_DECLTYPE:
+    case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
+    case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE:
+    case DEMANGLE_COMPONENT_PACK_EXPANSION:
+    case DEMANGLE_COMPONENT_TAGGED_NAME:
+    case DEMANGLE_COMPONENT_CLONE:
+    recurse_left_right:
+      d_count_templates_scopes (num_templates, num_scopes,
+				d_left (dc));
+      d_count_templates_scopes (num_templates, num_scopes,
+				d_right (dc));
+      break;
+
+    case DEMANGLE_COMPONENT_CTOR:
+      d_count_templates_scopes (num_templates, num_scopes,
+				dc->u.s_ctor.name);
+      break;
+
+    case DEMANGLE_COMPONENT_DTOR:
+      d_count_templates_scopes (num_templates, num_scopes,
+				dc->u.s_dtor.name);
+      break;
+
+    case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
+      d_count_templates_scopes (num_templates, num_scopes,
+				dc->u.s_extended_operator.name);
+      break;
+
+    case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
+    case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
+      d_count_templates_scopes (num_templates, num_scopes,
+				d_left (dc));
+      break;
+
+    case DEMANGLE_COMPONENT_LAMBDA:
+    case DEMANGLE_COMPONENT_DEFAULT_ARG:
+      d_count_templates_scopes (num_templates, num_scopes,
+				dc->u.s_unary_num.sub);
+      break;
+    }
+}
+
 /* Initialize a print information structure.  */
 
 static void
 d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
-	      void *opaque)
+	      void *opaque, const struct demangle_component *dc)
 {
   dpi->len = 0;
   dpi->last_char = '\0';
@@ -3789,29 +3928,18 @@  d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
   dpi->demangle_failure = 0;
 
   dpi->saved_scopes = NULL;
+  dpi->next_saved_scope = 0;
   dpi->num_saved_scopes = 0;
-  dpi->current_template = NULL;
-}
-
-/* Free a print information structure.  */
-
-static void
-d_print_free (struct d_print_info *dpi)
-{
-  int i;
 
-  for (i = 0; i < dpi->num_saved_scopes; i++)
-    {
-      struct d_print_template *ts, *tn;
+  dpi->copy_templates = NULL;
+  dpi->next_copy_template = 0;
+  dpi->num_copy_templates = 0;
 
-      for (ts = dpi->saved_scopes[i].templates; ts != NULL; ts = tn)
-	{
-	  tn = ts->next;
-	  free (ts);
-	}
-    }
+  d_count_templates_scopes (&dpi->num_copy_templates,
+			    &dpi->num_saved_scopes, dc);
+  dpi->num_copy_templates *= dpi->num_saved_scopes;
 
-  free (dpi->saved_scopes);
+  dpi->current_template = NULL;
 }
 
 /* Indicate that an error occurred during printing, and test for error.  */
@@ -3896,17 +4024,29 @@  cplus_demangle_print_callback (int options,
                                demangle_callbackref callback, void *opaque)
 {
   struct d_print_info dpi;
-  int success;
 
-  d_print_init (&dpi, callback, opaque);
+  d_print_init (&dpi, callback, opaque, dc);
+
+  {
+#ifdef CP_DYNAMIC_ARRAYS
+    __extension__ struct d_saved_scope scopes[dpi.num_saved_scopes];
+    __extension__ struct d_print_template temps[dpi.num_copy_templates];
+
+    dpi.saved_scopes = scopes;
+    dpi.copy_templates = temps;
+#else
+    dpi.saved_scopes = alloca (dpi.num_saved_scopes
+			       * sizeof (*dpi.saved_scopes));
+    dpi.copy_templates = alloca (dpi.num_copy_templates
+				 * sizeof (*dpi.copy_templates));
+#endif
 
-  d_print_comp (&dpi, options, dc);
+    d_print_comp (&dpi, options, dc);
+  }
 
   d_print_flush (&dpi);
 
-  success = ! d_print_saw_error (&dpi);
-  d_print_free (&dpi);
-  return success;
+  return ! d_print_saw_error (&dpi);
 }
 
 /* Turn components into a human readable string.  OPTIONS is the
@@ -4063,25 +4203,37 @@  d_print_subexpr (struct d_print_info *dpi, int options,
     d_append_char (dpi, ')');
 }
 
-/* Return a shallow copy of the current list of templates.
-   On error d_print_error is called and a partial list may
-   be returned.  Whatever is returned must be freed.  */
+/* Save the current scope.  */
 
-static struct d_print_template *
-d_copy_templates (struct d_print_info *dpi)
+static void
+d_save_scope (struct d_print_info *dpi,
+	      const struct demangle_component *container)
 {
-  struct d_print_template *src, *result, **link = &result;
+  struct d_saved_scope *scope;
+  struct d_print_template *src, **link;
+
+  if (dpi->next_saved_scope >= dpi->num_saved_scopes)
+    {
+      d_print_error (dpi);
+      return;
+    }
+  scope = &dpi->saved_scopes[dpi->next_saved_scope];
+  dpi->next_saved_scope++;
+
+  scope->container = container;
+  link = &scope->templates;
 
   for (src = dpi->templates; src != NULL; src = src->next)
     {
-      struct d_print_template *dst =
-	(struct d_print_template *) malloc (sizeof (struct d_print_template));
+      struct d_print_template *dst;
 
-      if (dst == NULL)
+      if (dpi->next_copy_template >= dpi->num_copy_templates)
 	{
 	  d_print_error (dpi);
-	  break;
+	  return;
 	}
+      dst = &dpi->copy_templates[dpi->next_copy_template];
+      dpi->next_copy_template++;
 
       dst->template_decl = src->template_decl;
       *link = dst;
@@ -4089,8 +4241,22 @@  d_copy_templates (struct d_print_info *dpi)
     }
 
   *link = NULL;
+}
+
+/* Attempt to locate a previously saved scope.  Returns NULL if no
+   corresponding saved scope was found.  */
+
+static struct d_saved_scope *
+d_get_saved_scope (struct d_print_info *dpi,
+		   const struct demangle_component *container)
+{
+  int i;
 
-  return result;
+  for (i = 0; i < dpi->next_saved_scope; i++)
+    if (dpi->saved_scopes[i].container == container)
+      return &dpi->saved_scopes[i];
+
+  return NULL;
 }
 
 /* Subroutine to handle components.  */
@@ -4485,37 +4651,16 @@  d_print_comp (struct d_print_info *dpi, int options,
 	const struct demangle_component *sub = d_left (dc);
 	if (sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
 	  {
+	    struct d_saved_scope *scope = d_get_saved_scope (dpi, sub);
 	    struct demangle_component *a;
-	    struct d_saved_scope *scope = NULL, *scopes;
-	    int i;
-
-	    for (i = 0; i < dpi->num_saved_scopes; i++)
-	      if (dpi->saved_scopes[i].container == sub)
-		scope = &dpi->saved_scopes[i];
 
 	    if (scope == NULL)
 	      {
-		size_t size;
-
 		/* This is the first time SUB has been traversed.
 		   We need to capture the current templates so
 		   they can be restored if SUB is reentered as a
 		   substitution.  */
-		++dpi->num_saved_scopes;
-		size = sizeof (struct d_saved_scope) * dpi->num_saved_scopes;
-		scopes = (struct d_saved_scope *) realloc (dpi->saved_scopes,
-							   size);
-		if (scopes == NULL)
-		  {
-		    d_print_error (dpi);
-		    return;
-		  }
-
-		dpi->saved_scopes = scopes;
-		scope = dpi->saved_scopes + (dpi->num_saved_scopes - 1);
-
-		scope->container = sub;
-		scope->templates = d_copy_templates (dpi);
+		d_save_scope (dpi, sub);
 		if (d_print_saw_error (dpi))
 		  return;
 	      }