* Fix fir PR71696 in Libiberty Demangler (6)
@ 2016-06-30 7:07 Marcel Böhme
2016-07-04 12:54 ` Bernd Schmidt
2016-07-21 17:01 ` Jeff Law
0 siblings, 2 replies; 6+ messages in thread
From: Marcel Böhme @ 2016-06-30 7:07 UTC (permalink / raw)
To: gcc-patches List
Hi,
The attached patch fixes the stack overflow in the demangler due to cycles in the references of “remembered” mangled types (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71696).
The methods demangle_signature and do_arg in cplus-dem.c allow to “remember” mangled type names that can later be referenced and will also be demangled. The method demangle_args demangles those types following any references. So, if there is a cycle in the referencing (or in the simplest case a self-reference), the method enters infinite recursion.
The patch tracks the mangled types that are currently being demangled in a new variable called work->proctypevec. If a referenced type is currently being demangled, the demangling is marked as not successful.
Bootstrapped and regression tested on x86_64-pc-linux-gnu. Test case added to libiberty/testsuite/demangler-expected and checked PR71696 is resolved.
Index: libiberty/ChangeLog
===================================================================
--- libiberty/ChangeLog (revision 237852)
+++ libiberty/ChangeLog (working copy)
@@ -1,3 +1,21 @@
+2016-06-30 Marcel Böhme <boehme.marcel@gmail.com>
+
+ * 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.
+
+ * testsuite/demangle-expected: Add tests.
+
2016-05-31 Alan Modra <amodra@gmail.com>
* xmemdup.c (xmemdup): Use xmalloc rather than xcalloc.
Index: libiberty/cplus-dem.c
===================================================================
--- libiberty/cplus-dem.c (revision 237852)
+++ libiberty/cplus-dem.c (working copy)
@@ -144,6 +144,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)
@@ -436,6 +439,10 @@ iterate_demangle_function (struct work_stuff *,
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 *);
@@ -1302,6 +1309,13 @@ work_stuff_copy_to_from (struct work_stuff *to, st
memcpy (to->btypevec[i], from->btypevec[i], len);
}
+ if (from->proctypevec)
+ {
+ to->proctypevec = XNEWVEC (int, from->proctypevec_size);
+ memcpy (to->proctypevec, from->proctypevec,
+ from->proctypevec_size * sizeof(int));
+ }
+
if (from->ntmpl_args)
to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
@@ -1336,6 +1350,12 @@ delete_non_B_K_work_stuff (struct work_stuff *work
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)
{
int i;
@@ -3554,6 +3574,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;
@@ -3566,6 +3588,7 @@ do_type (struct work_stuff *work, const char **man
done = 0;
success = 1;
+ is_proctypevec = 0;
while (success && !done)
{
int member;
@@ -3626,7 +3649,14 @@ do_type (struct work_stuff *work, const char **man
success = 0;
}
else
- {
+ 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;
}
@@ -3849,6 +3879,9 @@ do_type (struct work_stuff *work, const char **man
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);
@@ -4261,6 +4294,34 @@ do_arg (struct work_stuff *work, const char **mang
}
static void
+push_processed_type (struct work_stuff *work, int typevec_index)
+{
+ if (work -> nproctypes >= work -> proctypevec_size)
+ {
+ if (work -> proctypevec_size == 0)
+ {
+ work -> proctypevec_size = 3;
+ work -> proctypevec = XNEWVEC (int, work -> proctypevec_size);
+ }
+ else
+ {
+ if (work -> proctypevec_size > INT_MAX / 2)
+ xmalloc_failed (INT_MAX);
+ work -> proctypevec_size *= 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;
@@ -4524,10 +4585,13 @@ demangle_args (struct work_stuff *work, const char
{
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: libiberty/testsuite/demangle-expected
===================================================================
--- libiberty/testsuite/demangle-expected (revision 237852)
+++ libiberty/testsuite/demangle-expected (working copy)
@@ -4556,3 +4556,8 @@ __vt_90000000000cafebabe
_Z80800000000000000000000
_Z80800000000000000000000
+#
+# Tests stack overflow PR71696
+
+__10%0__S4_0T0T0
+%0<>::%0(%0<>)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Fix fir PR71696 in Libiberty Demangler (6)
2016-06-30 7:07 Fix fir PR71696 in Libiberty Demangler (6) Marcel Böhme
@ 2016-07-04 12:54 ` Bernd Schmidt
2016-07-18 2:31 ` Marcel Böhme
2016-07-21 17:01 ` Jeff Law
1 sibling, 1 reply; 6+ messages in thread
From: Bernd Schmidt @ 2016-07-04 12:54 UTC (permalink / raw)
To: Marcel Böhme, gcc-patches List
On 06/30/2016 08:46 AM, Marcel Böhme wrote:
> The attached patch fixes the stack overflow in the demangler due to
> cycles in the references of ârememberedâ mangled types
> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71696).
>
> The methods demangle_signature and do_arg in cplus-dem.c allow to
> ârememberâ mangled type names that can later be referenced and will
> also be demangled. The method demangle_args demangles those types
> following any references. So, if there is a cycle in the referencing
> (or in the simplest case a self-reference), the method enters
> infinite recursion.
>
> The patch tracks the mangled types that are currently being demangled
> in a new variable called work->proctypevec. If a referenced type is
> currently being demangled, the demangling is marked as not
> successful.
I'll defer reviewing these to someone who understands demangling better.
You might want to Cc Jason.
Bernd
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Fix fir PR71696 in Libiberty Demangler (6)
2016-07-04 12:54 ` Bernd Schmidt
@ 2016-07-18 2:31 ` Marcel Böhme
0 siblings, 0 replies; 6+ messages in thread
From: Marcel Böhme @ 2016-07-18 2:31 UTC (permalink / raw)
To: Jeff Law, gcc-patches List, Jason Merrill; +Cc: Bernd Schmidt
Hi,
This patch is still pending a full review.
Best regards,
- Marcel
> On 4 Jul 2016, at 8:54 PM, Bernd Schmidt <bschmidt@redhat.com> wrote:
>
> On 06/30/2016 08:46 AM, Marcel Böhme wrote:
>> The attached patch fixes the stack overflow in the demangler due to
>> cycles in the references of “remembered” mangled types
>> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71696).
>>
>> The methods demangle_signature and do_arg in cplus-dem.c allow to
>> “remember” mangled type names that can later be referenced and will
>> also be demangled. The method demangle_args demangles those types
>> following any references. So, if there is a cycle in the referencing
>> (or in the simplest case a self-reference), the method enters
>> infinite recursion.
>>
>> The patch tracks the mangled types that are currently being demangled
>> in a new variable called work->proctypevec. If a referenced type is
>> currently being demangled, the demangling is marked as not
>> successful.
>
> I'll defer reviewing these to someone who understands demangling better. You might want to Cc Jason.
>
>
> Bernd
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Fix fir PR71696 in Libiberty Demangler (6)
2016-06-30 7:07 Fix fir PR71696 in Libiberty Demangler (6) Marcel Böhme
2016-07-04 12:54 ` Bernd Schmidt
@ 2016-07-21 17:01 ` Jeff Law
2016-08-04 7:06 ` Marcel Böhme
1 sibling, 1 reply; 6+ messages in thread
From: Jeff Law @ 2016-07-21 17:01 UTC (permalink / raw)
To: Marcel Böhme, gcc-patches List
On 06/30/2016 12:46 AM, Marcel Böhme wrote:
> Hi,
>
> The attached patch fixes the stack overflow in the demangler due to cycles in the references of ârememberedâ mangled types (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71696).
>
> The methods demangle_signature and do_arg in cplus-dem.c allow to ârememberâ mangled type names that can later be referenced and will also be demangled. The method demangle_args demangles those types following any references. So, if there is a cycle in the referencing (or in the simplest case a self-reference), the method enters infinite recursion.
>
> The patch tracks the mangled types that are currently being demangled in a new variable called work->proctypevec. If a referenced type is currently being demangled, the demangling is marked as not successful.
>
> Bootstrapped and regression tested on x86_64-pc-linux-gnu. Test case added to libiberty/testsuite/demangler-expected and checked PR71696 is resolved.
>
>
> Index: libiberty/ChangeLog
> ===================================================================
> --- libiberty/ChangeLog (revision 237852)
> +++ libiberty/ChangeLog (working copy)
> @@ -1,3 +1,21 @@
> +2016-06-30 Marcel Böhme <boehme.marcel@gmail.com>
> +
> + * 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.
> +
> + * testsuite/demangle-expected: Add tests.
> +
> @@ -1302,6 +1309,13 @@ work_stuff_copy_to_from (struct work_stuff *to, st
> memcpy (to->btypevec[i], from->btypevec[i], len);
> }
>
> + if (from->proctypevec)
> + {
> + to->proctypevec = XNEWVEC (int, from->proctypevec_size);
> + memcpy (to->proctypevec, from->proctypevec,
> + from->proctypevec_size * sizeof(int));
> + }
Isn't this
to->proctypevec
= XDUPVEC (int, from->proctypevec, from->proctypevec_size);
> @@ -1336,6 +1350,12 @@ delete_non_B_K_work_stuff (struct work_stuff *work
> work -> typevec = NULL;
> work -> typevec_size = 0;
> }
> + if (work -> proctypevec != NULL)
> + {
> + free (work -> proctypevec);
> + work -> proctypevec = NULL;
> + work -> proctypevec_size = 0;
> + }
Whitespace nits. No whitespace around the "->". Can you fix the one
immediately above your new code as well? (there's many others in
cplus-dem.c, feel free to fix those as an independent patch).
I see similar whitespace nits in your changes to do_type.
> @@ -3566,6 +3588,7 @@ do_type (struct work_stuff *work, const char **man
>
> done = 0;
> success = 1;
> + is_proctypevec = 0;
> while (success && !done)
> {
> int member;
> @@ -3626,7 +3649,14 @@ do_type (struct work_stuff *work, const char **man
> success = 0;
> }
> else
> - {
> + for (i = 0; i < work -> nproctypes; i++)
> + if (work -> proctypevec [i] == n)
> + success = 0;
So presumably this doesn't happen all that often or this could get
expensive and we'd want something more efficient for searching, right?
> static void
> +push_processed_type (struct work_stuff *work, int typevec_index)
> +{
> + if (work -> nproctypes >= work -> proctypevec_size)
> + {
> + if (work -> proctypevec_size == 0)
> + {
> + work -> proctypevec_size = 3;
> + work -> proctypevec = XNEWVEC (int, work -> proctypevec_size);
> + }
> + else
> + {
> + if (work -> proctypevec_size > INT_MAX / 2)
> + xmalloc_failed (INT_MAX);
> + work -> proctypevec_size *= 2;
> + work -> proctypevec
> + = XRESIZEVEC (int, work->proctypevec, work->proctypevec_size);
> + }
> + }
> + work -> proctypevec [work -> nproctypes ++] = typevec_index;
"->" whitespace nits all over the place here. I thought we had a better
growing heuristic than just double every time.. Hmm, in gcc/vec.c we have:
/* Exponential growth. */
if (!alloc)
alloc = 4;
else if (alloc < 16)
/* Double when small. */
alloc = alloc * 2;
else
/* Grow slower when large. */
alloc = (alloc * 3 / 2);
/* If this is still too small, set it to the right size. */
if (alloc < desired)
alloc = desired;
Let's go with something similar here.
> +}
> +
> +static void
> +pop_processed_type (struct work_stuff *work)
> +{
> + work -> nproctypes --;
No whitespace around the "->" or "--".
Can you take care of the minor issues above, retest & repost?
THanks,
Jeff
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Fix fir PR71696 in Libiberty Demangler (6)
2016-07-21 17:01 ` Jeff Law
@ 2016-08-04 7:06 ` Marcel Böhme
2016-08-04 16:54 ` Jeff Law
0 siblings, 1 reply; 6+ messages in thread
From: Marcel Böhme @ 2016-08-04 7:06 UTC (permalink / raw)
To: Jeff Law; +Cc: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 755 bytes --]
Hi Jeff,
> Can you take care of the minor issues above, retest & repost?
Sure. I removed the whitespace nits, used XDUPVEC instead of XNEWVEC+memcpy, and adjusted the growing heuristics of the new array proctypevec. The revised patch is attached below. Bootstrapped and regression tested on x86_64-pc-linux-gnu and checked PR71696 is resolved.
>> + for (i = 0; i < work -> nproctypes; i++)
>> + if (work -> proctypevec [i] == n)
>> + success = 0;
> So presumably this doesn't happen all that often or this could get expensive
> and we'd want something more efficient for searching, right?
It seems, at least for the cases in the Demangler test suite, the loop executes never more than one iteration.
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 6529 bytes --]
Index: libiberty/ChangeLog
===================================================================
--- libiberty/ChangeLog (revision 239112)
+++ libiberty/ChangeLog (working copy)
@@ -1,3 +1,20 @@
+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.
+
2016-07-29 Aldy Hernandez <aldyh@redhat.com>
* make-relative-prefix.c (make_relative_prefix_1): Fall back to
@@ -16,7 +33,7 @@
(d_template_args_1): Split out from d_template_args.
(d_args_length): New.
-2016-07-13 Marcel BÃhme <boehme.marcel@gmail.com>
+2016-07-13 Marcel Böhme <boehme.marcel@gmail.com>
PR c++/70926
* cplus-dem.c: Handle large values and overflow when demangling
Index: libiberty/cplus-dem.c
===================================================================
--- libiberty/cplus-dem.c (revision 239112)
+++ libiberty/cplus-dem.c (working copy)
@@ -144,6 +144,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)
@@ -436,6 +439,10 @@ iterate_demangle_function (struct work_stuff *,
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 *);
@@ -1302,6 +1309,10 @@ work_stuff_copy_to_from (struct work_stuff *to, st
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);
@@ -1330,12 +1341,18 @@ delete_non_B_K_work_stuff (struct work_stuff *work
/* 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)
{
int i;
@@ -3555,6 +3572,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;
@@ -3567,6 +3586,7 @@ do_type (struct work_stuff *work, const char **man
done = 0;
success = 1;
+ is_proctypevec = 0;
while (success && !done)
{
int member;
@@ -3627,8 +3647,15 @@ do_type (struct work_stuff *work, const char **man
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;
@@ -3850,6 +3877,9 @@ do_type (struct work_stuff *work, const char **man
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);
@@ -4263,6 +4293,41 @@ do_arg (struct work_stuff *work, const char **mang
}
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;
@@ -4526,10 +4591,13 @@ demangle_args (struct work_stuff *work, const char
{
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: libiberty/testsuite/demangle-expected
===================================================================
--- libiberty/testsuite/demangle-expected (revision 239112)
+++ libiberty/testsuite/demangle-expected (working copy)
@@ -4587,3 +4587,8 @@ _Z80800000000000000000000
__t2m05B500000000000000000_
__t2m05B500000000000000000_
+#
+# Tests stack overflow PR71696
+
+__10%0__S4_0T0T0
+%0<>::%0(%0<>)
[-- Attachment #3: Type: text/plain, Size: 6539 bytes --]
Index: libiberty/ChangeLog
===================================================================
--- libiberty/ChangeLog (revision 239112)
+++ libiberty/ChangeLog (working copy)
@@ -1,3 +1,20 @@
+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.
+
2016-07-29 Aldy Hernandez <aldyh@redhat.com>
* make-relative-prefix.c (make_relative_prefix_1): Fall back to
@@ -16,7 +33,7 @@
(d_template_args_1): Split out from d_template_args.
(d_args_length): New.
-2016-07-13 Marcel BÃhme <boehme.marcel@gmail.com>
+2016-07-13 Marcel Böhme <boehme.marcel@gmail.com>
PR c++/70926
* cplus-dem.c: Handle large values and overflow when demangling
Index: libiberty/cplus-dem.c
===================================================================
--- libiberty/cplus-dem.c (revision 239112)
+++ libiberty/cplus-dem.c (working copy)
@@ -144,6 +144,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)
@@ -436,6 +439,10 @@ iterate_demangle_function (struct work_stuff *,
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 *);
@@ -1302,6 +1309,10 @@ work_stuff_copy_to_from (struct work_stuff *to, st
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);
@@ -1330,12 +1341,18 @@ delete_non_B_K_work_stuff (struct work_stuff *work
/* 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)
{
int i;
@@ -3555,6 +3572,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;
@@ -3567,6 +3586,7 @@ do_type (struct work_stuff *work, const char **man
done = 0;
success = 1;
+ is_proctypevec = 0;
while (success && !done)
{
int member;
@@ -3627,8 +3647,15 @@ do_type (struct work_stuff *work, const char **man
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;
@@ -3850,6 +3877,9 @@ do_type (struct work_stuff *work, const char **man
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);
@@ -4263,6 +4293,41 @@ do_arg (struct work_stuff *work, const char **mang
}
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;
@@ -4526,10 +4591,13 @@ demangle_args (struct work_stuff *work, const char
{
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: libiberty/testsuite/demangle-expected
===================================================================
--- libiberty/testsuite/demangle-expected (revision 239112)
+++ libiberty/testsuite/demangle-expected (working copy)
@@ -4587,3 +4587,8 @@ _Z80800000000000000000000
__t2m05B500000000000000000_
__t2m05B500000000000000000_
+#
+# Tests stack overflow PR71696
+
+__10%0__S4_0T0T0
+%0<>::%0(%0<>)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Fix fir PR71696 in Libiberty Demangler (6)
2016-08-04 7:06 ` Marcel Böhme
@ 2016-08-04 16:54 ` Jeff Law
0 siblings, 0 replies; 6+ messages in thread
From: Jeff Law @ 2016-08-04 16:54 UTC (permalink / raw)
To: Marcel Böhme; +Cc: gcc-patches List
On 08/04/2016 01:07 AM, Marcel Böhme wrote:
> Hi Jeff,
>
>> Can you take care of the minor issues above, retest & repost?
>
> Sure. I removed the whitespace nits, used XDUPVEC instead of XNEWVEC+memcpy, and adjusted the growing heuristics of the new array proctypevec. The revised patch is attached below. Bootstrapped and regression tested on x86_64-pc-linux-gnu and checked PR71696 is resolved.
>
>>> + for (i = 0; i < work -> nproctypes; i++)
>>> + if (work -> proctypevec [i] == n)
>>> + success = 0;
>> So presumably this doesn't happen all that often or this could get expensive
>> and we'd want something more efficient for searching, right?
>
> It seems, at least for the cases in the Demangler test suite, the loop executes never more than one iteration.
>
>
>
>
>
>
> Index: libiberty/ChangeLog
> ===================================================================
> --- libiberty/ChangeLog (revision 239112)
> +++ libiberty/ChangeLog (working copy)
> @@ -1,3 +1,20 @@
> +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.
THanks. Installed and BZ updated.
jeff
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2016-08-04 16:54 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-30 7:07 Fix fir PR71696 in Libiberty Demangler (6) Marcel Böhme
2016-07-04 12:54 ` Bernd Schmidt
2016-07-18 2:31 ` Marcel Böhme
2016-07-21 17:01 ` Jeff Law
2016-08-04 7:06 ` Marcel Böhme
2016-08-04 16:54 ` Jeff Law
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).