[1/2] C++: Sync libiberty with upstream GCC.

Message ID CABOHX+fXPMT5mDk7x866ZVw-+BWO_LTOFbve1HkHR3VeiXgJhg@mail.gmail.com
State New, archived
Headers

Commit Message

Iain Buclaw June 6, 2017, 8:35 p.m. UTC
  Hi,

This patch synchronizes GDB with GCC's copy of libiberty - the C++
demangling part.

Iain.

---
  

Patch

commit 39e6b55d17b4080609c4fb2826dbf937367dd00f
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Tue Jun 6 22:19:35 2017 +0200

    Sync libiberty with upstream GCC.
    
    libiberty/ChangeLog:
    
            PR demangler/80513
            * cp-demangle.c (d_number): Check for overflow.
            * cplus-dem.c (consume_count): Fix overflow check.
            (gnu_special): Check for underscore after thunk delta.
            * testsuite/demangle-expected: Add tests for overflows and invalid
            characters in thunks.
    
            * cp-demangle.c (MAX_RECURSION_COUNT): New constant.
            (struct d_print_info): Add recursion field.
            (d_print_init): Initialize recursion.
            (d_print_comp): Check and update d_print_info recursion depth.
    
            * cp-demangle.c (d_substitution): Return NULL if d_add_substitution
            fails.
    
            * cp-demangle.h (struct d_info): Remove did_subs field.
            * cp-demangle.c (struct d_info_checkpoint): Likewise.
            (d_template_param): Don't update did_subs.
            (d_substitution): Likewise.
            (d_checkpoint): Don't assign did_subs.
            (d_backtrack): Likewise.
            (cplus_demangle_init_info): Don't initialize did_subs.

diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 04832ff683..7b8d0b4cba 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -316,10 +316,12 @@  struct d_info_checkpoint
   const char *n;
   int next_comp;
   int next_sub;
-  int did_subs;
   int expansion;
 };
 
+/* Maximum number of times d_print_comp may be called recursively.  */
+#define MAX_RECURSION_COUNT 1024
+
 enum { D_PRINT_BUFFER_LENGTH = 256 };
 struct d_print_info
 {
@@ -342,6 +344,9 @@  struct d_print_info
   struct d_print_mod *modifiers;
   /* Set to 1 if we saw a demangling error.  */
   int demangle_failure;
+  /* Number of times d_print_comp was recursively called.  Should not
+     be bigger than MAX_RECURSION_COUNT.  */
+  int recursion;
   /* Non-zero if we're printing a lambda argument.  A template
      parameter reference actually means 'auto'.  */
   int is_lambda_arg;
@@ -1687,6 +1692,8 @@  d_number (struct d_info *di)
 	    ret = - ret;
 	  return ret;
 	}
+      if (ret > ((INT_MAX - (peek - '0')) / 10))
+        return -1;
       ret = ret * 10 + peek - '0';
       d_advance (di, 1);
       peek = d_peek_char (di);
@@ -3075,8 +3082,6 @@  d_template_param (struct d_info *di)
   if (param < 0)
     return NULL;
 
-  ++di->did_subs;
-
   return d_make_template_param (di, param);
 }
 
@@ -3846,8 +3851,6 @@  d_substitution (struct d_info *di, int prefix)
       if (id >= (unsigned int) di->next_sub)
 	return NULL;
 
-      ++di->did_subs;
-
       return di->subs[id];
     }
   else
@@ -3896,7 +3899,8 @@  d_substitution (struct d_info *di, int prefix)
 		  /* If there are ABI tags on the abbreviation, it becomes
 		     a substitution candidate.  */
 		  dc = d_abi_tags (di, dc);
-		  d_add_substitution (di, dc);
+		  if (! d_add_substitution (di, dc))
+		    return NULL;
 		}
 	      return dc;
 	    }
@@ -3912,7 +3916,6 @@  d_checkpoint (struct d_info *di, struct d_info_checkpoint *checkpoint)
   checkpoint->n = di->n;
   checkpoint->next_comp = di->next_comp;
   checkpoint->next_sub = di->next_sub;
-  checkpoint->did_subs = di->did_subs;
   checkpoint->expansion = di->expansion;
 }
 
@@ -3922,7 +3925,6 @@  d_backtrack (struct d_info *di, struct d_info_checkpoint *checkpoint)
   di->n = checkpoint->n;
   di->next_comp = checkpoint->next_comp;
   di->next_sub = checkpoint->next_sub;
-  di->did_subs = checkpoint->did_subs;
   di->expansion = checkpoint->expansion;
 }
 
@@ -4157,6 +4159,7 @@  d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
   dpi->opaque = opaque;
 
   dpi->demangle_failure = 0;
+  dpi->recursion = 0;
   dpi->is_lambda_arg = 0;
 
   dpi->component_stack = NULL;
@@ -5691,13 +5694,14 @@  d_print_comp (struct d_print_info *dpi, int options,
 	      struct demangle_component *dc)
 {
   struct d_component_stack self;
-  if (dc == NULL || dc->d_printing > 1)
+  if (dc == NULL || dc->d_printing > 1 || dpi->recursion > MAX_RECURSION_COUNT)
     {
       d_print_error (dpi);
       return;
     }
-  else
-    dc->d_printing++;
+
+  dc->d_printing++;
+  dpi->recursion++;
 
   self.dc = dc;
   self.parent = dpi->component_stack;
@@ -5707,6 +5711,7 @@  d_print_comp (struct d_print_info *dpi, int options,
 
   dpi->component_stack = self.parent;
   dc->d_printing--;
+  dpi->recursion--;
 }
 
 /* Print a Java dentifier.  For Java we try to handle encoded extended
@@ -6159,7 +6164,6 @@  cplus_demangle_init_info (const char *mangled, int options, size_t len,
      chars in the mangled string.  */
   di->num_subs = len;
   di->next_sub = 0;
-  di->did_subs = 0;
 
   di->last_name = NULL;
 
diff --git a/libiberty/cp-demangle.h b/libiberty/cp-demangle.h
index a2657755f1..d4a4ab604d 100644
--- a/libiberty/cp-demangle.h
+++ b/libiberty/cp-demangle.h
@@ -111,10 +111,6 @@  struct d_info
   int next_sub;
   /* The number of available entries in the subs array.  */
   int num_subs;
-  /* The number of substitutions which we actually made from the subs
-     array, plus the number of template parameter references we
-     saw.  */
-  int did_subs;
   /* The last name we saw, for constructors and destructors.  */
   struct demangle_component *last_name;
   /* A running total of the length of large expansions from the
diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
index a990e07297..81c17a3207 100644
--- a/libiberty/cplus-dem.c
+++ b/libiberty/cplus-dem.c
@@ -520,21 +520,17 @@  consume_count (const char **type)
 
   while (ISDIGIT ((unsigned char)**type))
     {
-      count *= 10;
-
-      /* Check for overflow.
-	 We assume that count is represented using two's-complement;
-	 no power of two is divisible by ten, so if an overflow occurs
-	 when multiplying by ten, the result will not be a multiple of
-	 ten.  */
-      if ((count % 10) != 0)
+      const int digit = **type - '0';
+      /* Check for overflow.  */
+      if (count > ((INT_MAX - digit) / 10))
 	{
 	  while (ISDIGIT ((unsigned char) **type))
 	    (*type)++;
 	  return -1;
 	}
 
-      count += **type - '0';
+      count *= 10;
+      count += digit;
       (*type)++;
     }
 
@@ -3173,6 +3169,8 @@  gnu_special (struct work_stuff *work, const char **mangled, string *declp)
       delta = consume_count (mangled);
       if (delta == -1)
 	success = 0;
+      else if (**mangled != '_')
+        success = 0;
       else
 	{
 	  char *method = internal_cplus_demangle (work, ++*mangled);
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 45c572268b..f2a12b9a7d 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -4720,3 +4720,18 @@  _ZdvMMMMMMMMMMMMMrrrrA_DTdvfp_fp_Eededilfdfdfdfd
 
 _Z1MA_aMMMMA_MMA_MMMMMMMMSt1MS_o11T0000000000t2M0oooozoooo
 _Z1MA_aMMMMA_MMA_MMMMMMMMSt1MS_o11T0000000000t2M0oooozoooo
+
+#
+# demangler/80513 Test for overflow in d_number
+_Z4294967297x
+_Z4294967297x
+
+#
+# demangler/80513 Test for bogus characters after __thunk_
+__thunk_16a_$_1x
+__thunk_16a_$_1x
+
+#
+# demangler/80513 Test for overflow in consume_count
+__thunk_4294967297__$_1x
+__thunk_4294967297__$_1x