From: Jakub Jelinek Date: Thu, 19 May 2016 12:04:11 +0000 (+0200) Subject: backport: re PR other/61321 (demangler crash on casts in template parameters) X-Git-Tag: releases/gcc-4.9.4~167 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3240894f3036746c7cf0dbf1ff0e419c8c71840b;p=thirdparty%2Fgcc.git backport: re PR other/61321 (demangler crash on casts in template parameters) Backported from mainline 2015-11-27 Pedro Alves PR other/61321 PR other/61233 * demangle.h (enum demangle_component_type) : New value. * cp-demangle.c (d_demangle_callback, d_make_comp): Handle DEMANGLE_COMPONENT_CONVERSION. (is_ctor_dtor_or_conversion): Handle DEMANGLE_COMPONENT_CONVERSION instead of DEMANGLE_COMPONENT_CAST. (d_operator_name): Return a DEMANGLE_COMPONENT_CONVERSION component if handling a conversion. (d_count_templates_scopes, d_print_comp_inner): Handle DEMANGLE_COMPONENT_CONVERSION. (d_print_comp_inner): Handle DEMANGLE_COMPONENT_CONVERSION instead of DEMANGLE_COMPONENT_CAST. (d_print_cast): Rename as ... (d_print_conversion): ... this. Adjust comments. (d_print_cast): Rewrite - simply print the left subcomponent. * cp-demint.c (cplus_demangle_fill_component): Handle DEMANGLE_COMPONENT_CONVERSION. * testsuite/demangle-expected: Add tests. From-SVN: r236455 --- diff --git a/include/ChangeLog b/include/ChangeLog index 59839bd57475..6ac4c4fd6e69 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,13 @@ +2016-05-19 Jakub Jelinek + + Backported from mainline + 2015-11-27 Pedro Alves + + PR other/61321 + PR other/61233 + * demangle.h (enum demangle_component_type) + : New value. + 2015-06-26 Release Manager * GCC 4.9.3 released. diff --git a/include/demangle.h b/include/demangle.h index bbad71bd8c74..7dc26489d6f9 100644 --- a/include/demangle.h +++ b/include/demangle.h @@ -373,6 +373,10 @@ enum demangle_component_type /* A typecast, represented as a unary operator. The one subtree is the type to which the argument should be cast. */ DEMANGLE_COMPONENT_CAST, + /* A conversion operator, represented as a unary operator. The one + subtree is the type to which the argument should be converted + to. */ + DEMANGLE_COMPONENT_CONVERSION, /* A nullary expression. The left subtree is the operator. */ DEMANGLE_COMPONENT_NULLARY, /* A unary expression. The left subtree is the operator, and the diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index f112f762a1eb..a32a08f0211b 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,6 +1,28 @@ 2016-05-19 Jakub Jelinek Backported from mainline + 2015-11-27 Pedro Alves + + PR other/61321 + PR other/61233 + * cp-demangle.c (d_demangle_callback, d_make_comp): Handle + DEMANGLE_COMPONENT_CONVERSION. + (is_ctor_dtor_or_conversion): Handle DEMANGLE_COMPONENT_CONVERSION + instead of DEMANGLE_COMPONENT_CAST. + (d_operator_name): Return a DEMANGLE_COMPONENT_CONVERSION + component if handling a conversion. + (d_count_templates_scopes, d_print_comp_inner): Handle + DEMANGLE_COMPONENT_CONVERSION. + (d_print_comp_inner): Handle DEMANGLE_COMPONENT_CONVERSION instead + of DEMANGLE_COMPONENT_CAST. + (d_print_cast): Rename as ... + (d_print_conversion): ... this. Adjust comments. + (d_print_cast): Rewrite - simply print the left subcomponent. + * cp-demint.c (cplus_demangle_fill_component): Handle + DEMANGLE_COMPONENT_CONVERSION. + + * testsuite/demangle-expected: Add tests. + 2015-07-13 Mikhail Maltsev * cp-demangle.c (d_dump): Fix syntax error. diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index fc58050e4bc2..3409fcda3237 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -538,8 +538,10 @@ d_print_array_type (struct d_print_info *, int, static void d_print_expr_op (struct d_print_info *, int, const struct demangle_component *); -static void -d_print_cast (struct d_print_info *, int, const struct demangle_component *); +static void d_print_cast (struct d_print_info *, int, + const struct demangle_component *); +static void d_print_conversion (struct d_print_info *, int, + const struct demangle_component *); static int d_demangle_callback (const char *, int, demangle_callbackref, void *); @@ -729,6 +731,9 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_CAST: printf ("cast\n"); break; + case DEMANGLE_COMPONENT_CONVERSION: + printf ("conversion operator\n"); + break; case DEMANGLE_COMPONENT_NULLARY: printf ("nullary operator\n"); break; @@ -938,6 +943,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_IMAGINARY: case DEMANGLE_COMPONENT_VENDOR_TYPE: case DEMANGLE_COMPONENT_CAST: + case DEMANGLE_COMPONENT_CONVERSION: case DEMANGLE_COMPONENT_JAVA_RESOURCE: case DEMANGLE_COMPONENT_DECLTYPE: case DEMANGLE_COMPONENT_PACK_EXPANSION: @@ -1229,7 +1235,7 @@ is_ctor_dtor_or_conversion (struct demangle_component *dc) return is_ctor_dtor_or_conversion (d_right (dc)); case DEMANGLE_COMPONENT_CTOR: case DEMANGLE_COMPONENT_DTOR: - case DEMANGLE_COMPONENT_CAST: + case DEMANGLE_COMPONENT_CONVERSION: return 1; } } @@ -1785,11 +1791,16 @@ d_operator_name (struct d_info *di) { struct demangle_component *type; int was_conversion = di->is_conversion; + struct demangle_component *res; di->is_conversion = ! di->is_expression; type = cplus_demangle_type (di); + if (di->is_conversion) + res = d_make_comp (di, DEMANGLE_COMPONENT_CONVERSION, type, NULL); + else + res = d_make_comp (di, DEMANGLE_COMPONENT_CAST, type, NULL); di->is_conversion = was_conversion; - return d_make_comp (di, DEMANGLE_COMPONENT_CAST, type, NULL); + return res; } else { @@ -3888,6 +3899,7 @@ d_count_templates_scopes (int *num_templates, int *num_scopes, case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: case DEMANGLE_COMPONENT_INITIALIZER_LIST: case DEMANGLE_COMPONENT_CAST: + case DEMANGLE_COMPONENT_CONVERSION: case DEMANGLE_COMPONENT_NULLARY: case DEMANGLE_COMPONENT_UNARY: case DEMANGLE_COMPONENT_BINARY: @@ -5021,9 +5033,9 @@ d_print_comp_inner (struct d_print_info *dpi, int options, d_print_comp (dpi, options, dc->u.s_extended_operator.name); return; - case DEMANGLE_COMPONENT_CAST: + case DEMANGLE_COMPONENT_CONVERSION: d_append_string (dpi, "operator "); - d_print_cast (dpi, options, dc); + d_print_conversion (dpi, options, dc); return; case DEMANGLE_COMPONENT_NULLARY: @@ -5756,11 +5768,20 @@ d_print_expr_op (struct d_print_info *dpi, int options, static void d_print_cast (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + const struct demangle_component *dc) +{ + d_print_comp (dpi, options, d_left (dc)); +} + +/* Print a conversion operator. */ + +static void +d_print_conversion (struct d_print_info *dpi, int options, + const struct demangle_component *dc) { struct d_print_template dpt; - /* For a cast operator, we need the template parameters from + /* For a conversion operator, we need the template parameters from the enclosing template in scope for processing the type. */ if (dpi->current_template != NULL) { diff --git a/libiberty/cp-demint.c b/libiberty/cp-demint.c index 1d1a77af748b..efcc5b7f5c02 100644 --- a/libiberty/cp-demint.c +++ b/libiberty/cp-demint.c @@ -110,6 +110,7 @@ cplus_demangle_fill_component (struct demangle_component *p, case DEMANGLE_COMPONENT_IMAGINARY: case DEMANGLE_COMPONENT_VENDOR_TYPE: case DEMANGLE_COMPONENT_CAST: + case DEMANGLE_COMPONENT_CONVERSION: if (right != NULL) return 0; break; diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index 4f793c469670..7038c7d13652 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -4383,3 +4383,26 @@ xxx _QueueNotification_QueueController__$4PPPPPPPM_A_INotice___Z _QueueNotification_QueueController__$4PPPPPPPM_A_INotice___Z _QueueNotification_QueueController__$4PPPPPPPM_A_INotice___Z +# +# These two are from gcc PR61321, and gcc PR61233 / gdb PR16957 +# +--format=gnu-v3 +_Z13function_tempIiEv1AIXszcvT_Li999EEE +void function_temp(A) +# +--format=gnu-v3 +_Z7ZipWithI7QStringS0_5QListZN4oral6detail16AdaptCreateTableI7AccountEES0_RKNS3_16CachedFieldsDataEEUlRKS0_SA_E_ET1_IDTclfp1_cvT__EcvT0__EEEERKT1_ISC_ERKT1_ISD_ET2_ +QList ZipWith(oral::detail::CachedFieldsData const&)::{lambda(QString const&, QString const&)#1}>(QList(oral::detail::CachedFieldsData const&)::{lambda(QString const&, QString const&)#1}> const&, QList const&, QString oral::detail::AdaptCreateTable(oral::detail::CachedFieldsData const&)::{lambda(QString const&, QString const&)#1}) +# +# These three are symbols generated by g++'s testsuite, which triggered the same bug as above. +--format=gnu-v3 +_Z14int_if_addableI1YERiP1AIXszpldecvPT_Li0EdecvS4_Li0EEE +int& int_if_addable(A*) +# +--format=gnu-v3 +_Z3bazIiEvP1AIXszcl3foocvT__ELCf00000000_00000000EEEE +void baz(A*) +# +--format=gnu-v3 +_Z3fooI1FEN1XIXszdtcl1PclcvT__EEE5arrayEE4TypeEv +X::Type foo() diff --git a/libiberty/testsuite/demangler-fuzzer.c b/libiberty/testsuite/demangler-fuzzer.c new file mode 100644 index 000000000000..aff702473010 --- /dev/null +++ b/libiberty/testsuite/demangler-fuzzer.c @@ -0,0 +1,108 @@ +/* Demangler fuzzer. + + Copyright (C) 2014 Free Software Foundation, Inc. + + This file is part of GNU libiberty. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include +#include +#include +#include +#include "demangle.h" + +#define MAXLEN 253 +#define ALPMIN 33 +#define ALPMAX 127 + +static char *program_name; + +#define DEFAULT_MAXCOUNT 7500000 + +static void +print_usage (FILE *fp, int exit_value) +{ + fprintf (fp, "Usage: %s [OPTION]...\n", program_name); + fprintf (fp, "Options:\n"); + fprintf (fp, " -h Display this message.\n"); + fprintf (fp, " -s SEED Select the random seed to be used.\n"); + fprintf (fp, " The default is to base one on the"); + fprintf (fp, " current time.\n"); + fprintf (fp, " -m MAXCOUNT Exit after MAXCOUNT symbols.\n"); + fprintf (fp, " The default is %d.", DEFAULT_MAXCOUNT); + fprintf (fp, " Set to `-1' for no limit.\n"); + + exit (exit_value); +} + +int +main (int argc, char *argv[]) +{ + char symbol[2 + MAXLEN + 1] = "_Z"; + int seed = -1, seed_set = 0; + int count = 0, maxcount = DEFAULT_MAXCOUNT; + int optchr; + + program_name = argv[0]; + + do + { + optchr = getopt (argc, argv, "hs:m:t:"); + switch (optchr) + { + case '?': /* Unrecognized option. */ + print_usage (stderr, 1); + break; + + case 'h': + print_usage (stdout, 0); + break; + + case 's': + seed = atoi (optarg); + seed_set = 1; + break; + + case 'm': + maxcount = atoi (optarg); + break; + } + } + while (optchr != -1); + + if (!seed_set) + seed = time (NULL); + srand (seed); + printf ("%s: seed = %d\n", program_name, seed); + + while (maxcount < 0 || count < maxcount) + { + char *buffer = symbol + 2; + int length, i; + + length = rand () % MAXLEN; + for (i = 0; i < length; i++) + *buffer++ = (rand () % (ALPMAX - ALPMIN)) + ALPMIN; + + *buffer++ = '\0'; + + cplus_demangle (symbol, DMGL_AUTO | DMGL_ANSI | DMGL_PARAMS); + + count++; + } + + printf ("%s: successfully demangled %d symbols\n", program_name, count); + exit (0); +}