File gdb-libiberty-demangler-fuzz.diff of Package gdb.3129

Fix for GCC PR71696, and hence bnc#987637
(infinite recursion with crafted input)

(Also adds xmalloc_failed() to common-utils.c, as otherwise building
fails with duplicate symbols as libiberty/xmalloc.o is linked in)
2016-08-04  Marcel Böhme  <boehme.marcel@gmail.com>

	PR c++/71696
	* cplus-dem.c: Prevent infinite recursion when there is a cycle
	in the referencing of remembered mangled types.
	(work_stuff): New stack to keep track of the remembered mangled
	types that are currently being processed.
	(push_processed_type): New method to push currently processed
	remembered type onto the stack.
	(pop_processed_type): New method to pop currently processed
	remembered type from the stack.
	(work_stuff_copy_to_from): Copy values of new variables.
	(delete_non_B_K_work_stuff): Free stack memory.
	(demangle_args): Push/Pop currently processed remembered type.
	(do_type): Do not demangle a cyclic reference and push/pop
	referenced remembered type.

Index: libiberty/testsuite/demangle-expected
===================================================================
--- libiberty/testsuite/demangle-expected.orig	2016-08-26 16:32:53.000000000 +0200
+++ libiberty/testsuite/demangle-expected	2016-08-26 16:38:05.000000000 +0200
@@ -4421,3 +4421,8 @@ void baz<int>(A<sizeof (foo((int)(), (fl
 --format=gnu-v3
 _Z3fooI1FEN1XIXszdtcl1PclcvT__EEE5arrayEE4TypeEv
 X<sizeof ((P(((F)())())).array)>::Type foo<F>()
+#
+# Tests stack overflow PR71696
+
+__10%0__S4_0T0T0
+%0<>::%0(%0<>)
Index: libiberty/cplus-dem.c
===================================================================
--- libiberty/cplus-dem.c.orig	2016-08-26 16:32:53.000000000 +0200
+++ libiberty/cplus-dem.c	2016-08-26 16:38:05.000000000 +0200
@@ -45,6 +45,9 @@ Boston, MA 02110-1301, USA.  */
 
 #include "safe-ctype.h"
 
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
 #include <sys/types.h>
 #include <string.h>
 #include <stdio.h>
@@ -137,6 +140,9 @@ struct work_stuff
   string* previous_argument; /* The last function argument demangled.  */
   int nrepeats;         /* The number of times to repeat the previous
 			   argument.  */
+  int *proctypevec;     /* Indices of currently processed remembered typevecs.  */
+  int proctypevec_size;
+  int nproctypes;
 };
 
 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
@@ -428,6 +434,10 @@ iterate_demangle_function (struct work_s
 
 static void remember_type (struct work_stuff *, const char *, int);
 
+static void push_processed_type (struct work_stuff *, int);
+
+static void pop_processed_type (struct work_stuff *);
+
 static void remember_Btype (struct work_stuff *, const char *, int, int);
 
 static int register_Btype (struct work_stuff *);
@@ -1292,6 +1302,10 @@ work_stuff_copy_to_from (struct work_stu
       memcpy (to->btypevec[i], from->btypevec[i], len);
     }
 
+  if (from->proctypevec)
+    to->proctypevec =
+      XDUPVEC (int, from->proctypevec, from->proctypevec_size);
+
   if (from->ntmpl_args)
     to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
 
@@ -1320,11 +1334,17 @@ delete_non_B_K_work_stuff (struct work_s
   /* Discard the remembered types, if any.  */
 
   forget_types (work);
-  if (work -> typevec != NULL)
+  if (work->typevec != NULL)
     {
-      free ((char *) work -> typevec);
-      work -> typevec = NULL;
-      work -> typevec_size = 0;
+      free ((char *) work->typevec);
+      work->typevec = NULL;
+      work->typevec_size = 0;
+    }
+  if (work->proctypevec != NULL)
+    {
+      free (work->proctypevec);
+      work->proctypevec = NULL;
+      work->proctypevec_size = 0;
     }
   if (work->tmpl_argvec)
     {
@@ -3538,6 +3558,8 @@ static int
 do_type (struct work_stuff *work, const char **mangled, string *result)
 {
   int n;
+  int i;
+  int is_proctypevec;
   int done;
   int success;
   string decl;
@@ -3550,6 +3572,7 @@ do_type (struct work_stuff *work, const
 
   done = 0;
   success = 1;
+  is_proctypevec = 0;
   while (success && !done)
     {
       int member;
@@ -3602,8 +3625,15 @@ do_type (struct work_stuff *work, const
 	      success = 0;
 	    }
 	  else
-	    {
-	      remembered_type = work -> typevec[n];
+	    for (i = 0; i < work->nproctypes; i++)
+	      if (work -> proctypevec [i] == n)
+	        success = 0;
+
+	  if (success)
+	    {    
+	      is_proctypevec = 1;
+	      push_processed_type (work, n);
+	      remembered_type = work->typevec[n];
 	      mangled = &remembered_type;
 	    }
 	  break;
@@ -3826,6 +3856,9 @@ do_type (struct work_stuff *work, const
     string_delete (result);
   string_delete (&decl);
 
+  if (is_proctypevec)
+    pop_processed_type (work); 
+
   if (success)
     /* Assume an integral type, if we're not sure.  */
     return (int) ((tk == tk_none) ? tk_integral : tk);
@@ -4238,6 +4271,41 @@ do_arg (struct work_stuff *work, const c
 }
 
 static void
+push_processed_type (struct work_stuff *work, int typevec_index)
+{
+  if (work->nproctypes >= work->proctypevec_size)
+    {
+      if (!work->proctypevec_size)
+	{
+	  work->proctypevec_size = 4;
+	  work->proctypevec = XNEWVEC (int, work->proctypevec_size);
+	}
+      else 
+	{
+	  if (work->proctypevec_size < 16)
+	    /* Double when small.  */
+	    work->proctypevec_size *= 2;
+	  else
+	    {
+	      /* Grow slower when large.  */
+	      if (work->proctypevec_size > (INT_MAX / 3) * 2)
+                xmalloc_failed (INT_MAX);
+              work->proctypevec_size = (work->proctypevec_size * 3 / 2);
+	    }   
+          work->proctypevec
+            = XRESIZEVEC (int, work->proctypevec, work->proctypevec_size);
+	}
+    }
+    work->proctypevec [work->nproctypes++] = typevec_index;
+}
+
+static void
+pop_processed_type (struct work_stuff *work)
+{
+  work->nproctypes--;
+}
+
+static void
 remember_type (struct work_stuff *work, const char *start, int len)
 {
   char *tem;
@@ -4495,10 +4563,13 @@ demangle_args (struct work_stuff *work,
 		{
 		  string_append (declp, ", ");
 		}
+	      push_processed_type (work, t);  
 	      if (!do_arg (work, &tem, &arg))
 		{
+		  pop_processed_type (work);
 		  return (0);
 		}
+	      pop_processed_type (work);
 	      if (PRINT_ARG_TYPES)
 		{
 		  string_appends (declp, &arg);
Index: gdb/common/common-utils.c
===================================================================
--- gdb/common/common-utils.c.orig	2016-08-25 16:27:39.000000000 +0200
+++ gdb/common/common-utils.c	2016-08-26 16:44:25.000000000 +0200
@@ -103,6 +103,12 @@ xfree (void *ptr)
     free (ptr);		/* ARI: free */
 }
 
+void
+xmalloc_failed (size_t size)
+{
+  malloc_failure (size);
+}
+
 /* Like asprintf/vasprintf but get an internal_error if the call
    fails. */
 
openSUSE Build Service is sponsored by