| From 59a0e4bd8391962f62600ae3ac95ab0fba74d464 Mon Sep 17 00:00:00 2001 |
| From: law <law@138bc75d-0d04-0410-961f-82ee72b054a4> |
| Date: Thu, 4 Aug 2016 16:53:18 +0000 |
| Subject: [PATCH] Fix for PR71696 in Libiberty Demangler |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| [BZ #71696] -- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71696 |
| |
| 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. |
| |
| cherry-picked from commit of |
| git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@239143 138bc75d-0d04-0410-961f-82ee72b054a4 |
| |
| Upstream-Status: Backport [master] |
| CVE: CVE-2016-6131 |
| Signed-off-by: Yuanjie Huang <yuanjie.huang@windriver.com> |
| --- |
| libiberty/ChangeLog | 17 ++++++++ |
| libiberty/cplus-dem.c | 78 ++++++++++++++++++++++++++++++++--- |
| libiberty/testsuite/demangle-expected | 18 ++++++++ |
| 3 files changed, 108 insertions(+), 5 deletions(-) |
| |
| Index: gcc-6.4.0/libiberty/cplus-dem.c |
| =================================================================== |
| --- gcc-6.4.0.orig/libiberty/cplus-dem.c |
| +++ gcc-6.4.0/libiberty/cplus-dem.c |
| @@ -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) |
| @@ -435,6 +438,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 *); |
| @@ -1301,6 +1308,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); |
| |
| @@ -1329,11 +1340,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) |
| { |
| @@ -3552,6 +3569,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; |
| @@ -3564,6 +3583,7 @@ do_type (struct work_stuff *work, const |
| |
| done = 0; |
| success = 1; |
| + is_proctypevec = 0; |
| while (success && !done) |
| { |
| int member; |
| @@ -3616,8 +3636,15 @@ do_type (struct work_stuff *work, const |
| success = 0; |
| } |
| else |
| + for (i = 0; i < work->nproctypes; i++) |
| + if (work -> proctypevec [i] == n) |
| + success = 0; |
| + |
| + if (success) |
| { |
| - remembered_type = work -> typevec[n]; |
| + is_proctypevec = 1; |
| + push_processed_type (work, n); |
| + remembered_type = work->typevec[n]; |
| mangled = &remembered_type; |
| } |
| break; |
| @@ -3840,6 +3867,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); |
| @@ -4252,6 +4282,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; |
| @@ -4515,10 +4580,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: gcc-6.4.0/libiberty/testsuite/demangle-expected |
| =================================================================== |
| --- gcc-6.4.0.orig/libiberty/testsuite/demangle-expected |
| +++ gcc-6.4.0/libiberty/testsuite/demangle-expected |
| @@ -4491,3 +4491,21 @@ void eat<int*, Foo()::{lambda(auto:1*, a |
| |
| _Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_ |
| void eat<int*, void Bar<short>()::{lambda(short*, auto:1*, auto:2*)#2}>(int*&, void Bar<short>()::{lambda(short*, auto:1*, auto:2*)#2}&) |
| +# |
| +# Tests write access violation PR70926 |
| + |
| +0__Ot2m02R5T0000500000 |
| +0__Ot2m02R5T0000500000 |
| +# |
| + |
| +0__GT50000000000_ |
| +0__GT50000000000_ |
| +# |
| + |
| +__t2m05B500000000000000000_ |
| +__t2m05B500000000000000000_ |
| +# |
| +# Tests stack overflow PR71696 |
| + |
| +__10%0__S4_0T0T0 |
| +%0<>::%0(%0<>) |