diff options
Diffstat (limited to 'debian/patches/libiberty-updates.diff')
-rw-r--r-- | debian/patches/libiberty-updates.diff | 2647 |
1 files changed, 2647 insertions, 0 deletions
diff --git a/debian/patches/libiberty-updates.diff b/debian/patches/libiberty-updates.diff new file mode 100644 index 0000000..caae314 --- /dev/null +++ b/debian/patches/libiberty-updates.diff @@ -0,0 +1,2647 @@ +# DP: libiberty updates, taken from the trunk 20161108 + +2016-11-30 David Malcolm <dmalcolm@redhat.com> + + PR c/78498 + * strndup.c (strlen): Delete decl. + (strnlen): Add decl. + (strndup): Call strnlen rather than strlen. + * xstrndup.c (xstrndup): Likewise. + +2016-11-29 Nathan Sidwell <nathan@acm.org> + + * cp-demangle.c (d_print_comp_inner): Fix parameter indentation. + +2016-11-03 David Tolnay <dtolnay@gmail.com> + Mark Wielaard <mark@klomp.org> + + * Makefile.in (CFILES): Add rust-demangle.c. + (REQUIRED_OFILES): Add rust-demangle.o. + * cplus-dem.c (libiberty_demanglers): Add rust_demangling case. + (cplus_demangle): Handle RUST_DEMANGLING. + (rust_demangle): New function. + * rust-demangle.c: New file. + * testsuite/Makefile.in (really-check): Add check-rust-demangle. + (check-rust-demangle): New rule. + * testsuite/rust-demangle-expected: New file. + +2016-11-15 Mark Wielaard <mark@klomp.org> + + * cp-demangle.c (d_expression_1): Make sure third expression + exists for ?: and fold expressions. + * testsuite/demangle-expected: Add examples of strings that could + crash the demangler because of missing expression. + +2016-11-14 Mark Wielaard <mark@klomp.org> + + * cplus-dem.c (demangle_signature): After 'H', template function, + no success and don't advance position if end of string reached. + (demangle_template): After 'z', template name, return zero on + premature end of string. + (gnu_special): Guard strchr against searching for zero characters. + (do_type): If member, only advance mangled string when 'F' found. + * testsuite/demangle-expected: Add examples of strings that could + crash the demangler by reading past end of input. + +2016-11-06 Mark Wielaard <mark@klomp.org> + + * configure.ac (ac_libiberty_warn_cflags): Add -Wshadow=local. + * configure: Regenerated. + +2016-11-07 Jason Merrill <jason@redhat.com> + + * cp-demangle.c (is_fnqual_component_type): New. + (d_encoding, d_print_comp_inner, d_print_mod_list): Use it. + (FNQUAL_COMPONENT_CASE): New. + (d_make_comp, has_return_type, d_print_comp_inner) + (d_print_function_type): Use it. + (next_is_type_qual): New. + (d_cv_qualifiers, d_print_mod): Handle noexcept and throw-spec. + +2016-11-02 Mark Wielaard <mjw@redhat.com> + + * cplus-dem.c (demangle_signature): Move fall through comment. + (demangle_fund_type): Add fall through comment between 'G' and 'I'. + * hashtab.c (iterative_hash): Add fall through comments. + * regex.c (regex_compile): Add Fall through comment after '+'/'?'. + (byte_re_match_2_internal): Add Fall through comment after jump_n. + Change "Note fall through" to "Fall through". + (common_op_match_null_string_p): Return false after set_number_at + instead of fall through. + +2016-11-01 Jason Merrill <jason@redhat.com> + + * cp-demangle.c (d_ctor_dtor_name): Handle inheriting constructor. + +2016-10-31 Mark Wielaard <mjw@redhat.com> + + * cplus-dem.c (ada_demangle): Initialize demangled to NULL and + XDELETEVEC demangled when unknown. + +2016-09-19 Andrew Stubbs <ams@codesourcery.com> + + * pex-win32.c (argv_to_cmdline): Quote zero-length parameters. + * testsuite/test-pexecute.c (main): Insert check for zero-length parameters. + +2016-09-10 Mark Wielaard <mjw@redhat.com> + + * cp-demangle.c (d_substitution): Change struct demangle_component + variable name from c to dc. + +2016-08-12 Marek Polacek <polacek@redhat.com> + + PR c/7652 + * cp-demangle.c (d_print_mod): Add FALLTHRU. + +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 + malloc if alloca argument is greater than MAX_ALLOCA_SIZE. + +2016-07-15 Jason Merrill <jason@redhat.com> + + * cp-demangle.c (cplus_demangle_operators): Add f[lrLR]. + (d_expression_1): Handle them. + (d_maybe_print_fold_expression): New. + (d_print_comp_inner): Use it. + (d_index_template_argument): Handle negative index. + + * cp-demangle.c (cplus_demangle_operators): Add sP and sZ. + (d_print_comp_inner): Handle them. + (d_template_args_1): Split out from d_template_args. + (d_args_length): New. + +2016-07-13 Marcel Böhme <boehme.marcel@gmail.com> + + PR c++/70926 + * cplus-dem.c: Handle large values and overflow when demangling + length variables. + (demangle_template_value_parm): Read only until end of mangled string. + (do_hpacc_template_literal): Likewise. + (do_type): Handle overflow when demangling array indices. + +2016-06-12 Brooks Moses <bmoses@google.com> + + * cp-demangle.c (cplus_demangle_print_callback): Avoid zero-length + VLAs. + +2016-05-31 Alan Modra <amodra@gmail.com> + + * xmemdup.c (xmemdup): Use xmalloc rather than xcalloc. + +2016-05-19 Jakub Jelinek <jakub@redhat.com> + + PR c++/70498 + * cp-demangle.c (d_expression_1): Formatting fix. + +2016-05-18 Artemiy Volkov <artemiyv@acm.org> + + * cplus-dem.c (enum type_kind_t): Add tk_rvalue_reference + constant. + (demangle_template_value_parm): Handle tk_rvalue_reference + type kind. + (do_type): Support 'O' type id (rvalue references). + + * testsuite/demangle-expected: Add tests. + +Index: b/src/libiberty/argv.c +=================================================================== +--- a/src/libiberty/argv.c ++++ b/src/libiberty/argv.c +@@ -35,6 +35,13 @@ Boston, MA 02110-1301, USA. */ + #include <string.h> + #include <stdlib.h> + #include <stdio.h> ++#include <sys/types.h> ++#ifdef HAVE_UNISTD_H ++#include <unistd.h> ++#endif ++#if HAVE_SYS_STAT_H ++#include <sys/stat.h> ++#endif + + #ifndef NULL + #define NULL 0 +@@ -387,6 +394,9 @@ expandargv (int *argcp, char ***argvp) + char **file_argv; + /* The number of options read from the response file, if any. */ + size_t file_argc; ++#ifdef S_ISDIR ++ struct stat sb; ++#endif + /* We are only interested in options of the form "@file". */ + filename = (*argvp)[i]; + if (filename[0] != '@') +@@ -397,6 +407,15 @@ expandargv (int *argcp, char ***argvp) + fprintf (stderr, "%s: error: too many @-files encountered\n", (*argvp)[0]); + xexit (1); + } ++#ifdef S_ISDIR ++ if (stat (filename+1, &sb) < 0) ++ continue; ++ if (S_ISDIR(sb.st_mode)) ++ { ++ fprintf (stderr, "%s: error: @-file refers to a directory\n", (*argvp)[0]); ++ xexit (1); ++ } ++#endif + /* Read the contents of the file. */ + f = fopen (++filename, "r"); + if (!f) +Index: b/src/libiberty/ChangeLog +=================================================================== +--- a/src/libiberty/ChangeLog ++++ b/src/libiberty/ChangeLog +@@ -22,11 +22,126 @@ + printing. + * testsuite/demangle-expected: Add lambda auto mangling cases. + +-2016-08-22 Release Manager ++2016-12-06 DJ Delorie <dj@redhat.com> + +- * GCC 6.2.0 released. ++ * argv.c (expandargv): Check for directories passed as @-files. + +-2016-07-21 Jason Merrill <jason@redhat.com> ++2016-11-30 David Malcolm <dmalcolm@redhat.com> ++ ++ PR c/78498 ++ * strndup.c (strlen): Delete decl. ++ (strnlen): Add decl. ++ (strndup): Call strnlen rather than strlen. ++ * xstrndup.c (xstrndup): Likewise. ++ ++2016-11-29 Nathan Sidwell <nathan@acm.org> ++ ++ * cp-demangle.c (d_print_comp_inner): Fix parameter indentation. ++ ++2016-11-03 David Tolnay <dtolnay@gmail.com> ++ Mark Wielaard <mark@klomp.org> ++ ++ * Makefile.in (CFILES): Add rust-demangle.c. ++ (REQUIRED_OFILES): Add rust-demangle.o. ++ * cplus-dem.c (libiberty_demanglers): Add rust_demangling case. ++ (cplus_demangle): Handle RUST_DEMANGLING. ++ (rust_demangle): New function. ++ * rust-demangle.c: New file. ++ * testsuite/Makefile.in (really-check): Add check-rust-demangle. ++ (check-rust-demangle): New rule. ++ * testsuite/rust-demangle-expected: New file. ++ ++2016-11-15 Mark Wielaard <mark@klomp.org> ++ ++ * cp-demangle.c (d_expression_1): Make sure third expression ++ exists for ?: and fold expressions. ++ * testsuite/demangle-expected: Add examples of strings that could ++ crash the demangler because of missing expression. ++ ++2016-11-14 Mark Wielaard <mark@klomp.org> ++ ++ * cplus-dem.c (demangle_signature): After 'H', template function, ++ no success and don't advance position if end of string reached. ++ (demangle_template): After 'z', template name, return zero on ++ premature end of string. ++ (gnu_special): Guard strchr against searching for zero characters. ++ (do_type): If member, only advance mangled string when 'F' found. ++ * testsuite/demangle-expected: Add examples of strings that could ++ crash the demangler by reading past end of input. ++ ++2016-11-06 Mark Wielaard <mark@klomp.org> ++ ++ * configure.ac (ac_libiberty_warn_cflags): Add -Wshadow=local. ++ * configure: Regenerated. ++ ++2016-11-07 Jason Merrill <jason@redhat.com> ++ ++ * cp-demangle.c (is_fnqual_component_type): New. ++ (d_encoding, d_print_comp_inner, d_print_mod_list): Use it. ++ (FNQUAL_COMPONENT_CASE): New. ++ (d_make_comp, has_return_type, d_print_comp_inner) ++ (d_print_function_type): Use it. ++ (next_is_type_qual): New. ++ (d_cv_qualifiers, d_print_mod): Handle noexcept and throw-spec. ++ ++2016-11-02 Mark Wielaard <mjw@redhat.com> ++ ++ * cplus-dem.c (demangle_signature): Move fall through comment. ++ (demangle_fund_type): Add fall through comment between 'G' and 'I'. ++ * hashtab.c (iterative_hash): Add fall through comments. ++ * regex.c (regex_compile): Add Fall through comment after '+'/'?'. ++ (byte_re_match_2_internal): Add Fall through comment after jump_n. ++ Change "Note fall through" to "Fall through". ++ (common_op_match_null_string_p): Return false after set_number_at ++ instead of fall through. ++ ++2016-11-01 Jason Merrill <jason@redhat.com> ++ ++ * cp-demangle.c (d_ctor_dtor_name): Handle inheriting constructor. ++ ++2016-10-31 Mark Wielaard <mjw@redhat.com> ++ ++ * cplus-dem.c (ada_demangle): Initialize demangled to NULL and ++ XDELETEVEC demangled when unknown. ++ ++2016-09-19 Andrew Stubbs <ams@codesourcery.com> ++ ++ * pex-win32.c (argv_to_cmdline): Quote zero-length parameters. ++ * testsuite/test-pexecute.c (main): Insert check for zero-length parameters. ++ ++2016-09-10 Mark Wielaard <mjw@redhat.com> ++ ++ * cp-demangle.c (d_substitution): Change struct demangle_component ++ variable name from c to dc. ++ ++2016-08-12 Marek Polacek <polacek@redhat.com> ++ ++ PR c/7652 ++ * cp-demangle.c (d_print_mod): Add FALLTHRU. ++ ++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 ++ malloc if alloca argument is greater than MAX_ALLOCA_SIZE. ++ ++2016-07-15 Jason Merrill <jason@redhat.com> + + * cp-demangle.c (cplus_demangle_operators): Add f[lrLR]. + (d_expression_1): Handle them. +@@ -39,15 +154,40 @@ + (d_template_args_1): Split out from d_template_args. + (d_args_length): New. + +-2016-05-19 Jakub Jelinek <jakub@redhat.com> ++2016-07-13 Marcel Böhme <boehme.marcel@gmail.com> ++ ++ PR c++/70926 ++ * cplus-dem.c: Handle large values and overflow when demangling ++ length variables. ++ (demangle_template_value_parm): Read only until end of mangled string. ++ (do_hpacc_template_literal): Likewise. ++ (do_type): Handle overflow when demangling array indices. ++ ++2016-06-12 Brooks Moses <bmoses@google.com> ++ ++ * cp-demangle.c (cplus_demangle_print_callback): Avoid zero-length ++ VLAs. + +- Backported from mainline +- 2016-05-19 Jakub Jelinek <jakub@redhat.com> ++2016-05-31 Alan Modra <amodra@gmail.com> ++ ++ * xmemdup.c (xmemdup): Use xmalloc rather than xcalloc. ++ ++2016-05-19 Jakub Jelinek <jakub@redhat.com> + + PR c++/70498 + * cp-demangle.c (d_expression_1): Formatting fix. + +- 2016-05-02 Marcel Böhme <boehme.marcel@gmail.com> ++2016-05-18 Artemiy Volkov <artemiyv@acm.org> ++ ++ * cplus-dem.c (enum type_kind_t): Add tk_rvalue_reference ++ constant. ++ (demangle_template_value_parm): Handle tk_rvalue_reference ++ type kind. ++ (do_type): Support 'O' type id (rvalue references). ++ ++ * testsuite/demangle-expected: Add tests. ++ ++2016-05-02 Marcel Böhme <boehme.marcel@gmail.com> + + PR c++/70498 + * cp-demangle.c: Parse numbers as integer instead of long to avoid +@@ -66,9 +206,9 @@ + (d_unnamed_type): Likewise. + * testsuite/demangle-expected: Add regression test cases. + +-2016-04-27 Release Manager ++2016-04-30 Oleg Endo <olegendo@gcc.gnu.org> + +- * GCC 6.1.0 released. ++ * configure: Remove SH5 support. + + 2016-04-08 Marcel Böhme <boehme.marcel@gmail.com> + +@@ -141,8 +281,6 @@ + + PR other/61321 + PR other/61233 +- * demangle.h (enum demangle_component_type) +- <DEMANGLE_COMPONENT_CONVERSION>: New value. + * cp-demangle.c (d_demangle_callback, d_make_comp): Handle + DEMANGLE_COMPONENT_CONVERSION. + (is_ctor_dtor_or_conversion): Handle DEMANGLE_COMPONENT_CONVERSION +@@ -729,11 +867,11 @@ + 2013-05-31 Matt Burgess <matthew@linuxfromscratch.org> + + PR other/56780 +- * libiberty/configure.ac: Move test for --enable-install-libiberty ++ * configure.ac: Move test for --enable-install-libiberty + outside of the 'with_target_subdir' test so that it actually gets + run. Add output messages to show the test result. +- * libiberty/configure: Regenerate. +- * libiberty/Makefile.in (install_to_libdir): Place the ++ * configure: Regenerate. ++ * Makefile.in (install_to_libdir): Place the + installation of the libiberty library in the same guard as that + used for the headers to prevent it being installed unless + requested via --enable-install-libiberty. +@@ -1533,7 +1671,6 @@ + Daniel Jacobowitz <dan@codesourcery.com> + Pedro Alves <pedro@codesourcery.com> + +- libiberty/ + * argv.c (consume_whitespace): New function. + (only_whitespace): New function. + (buildargv): Always use ISSPACE by calling consume_whitespace. +@@ -1734,8 +1871,8 @@ + + 2009-04-07 Arnaud Patard <apatard@mandriva.com> + +- * libiberty/configure.ac: Fix Linux/MIPS matching rule. +- * libiberty/configure: Regenerate. ++ * configure.ac: Fix Linux/MIPS matching rule. ++ * configure: Regenerate. + + 2009-03-27 Ian Lance Taylor <iant@google.com> + +@@ -1898,8 +2035,8 @@ + + 2008-04-21 Aurelien Jarno <aurelien@aurel32.net> + +- * libiberty/configure.ac: use -fPIC on Linux/MIPS hosts. +- * libiberty/configure: Regenerate. ++ * configure.ac: use -fPIC on Linux/MIPS hosts. ++ * configure: Regenerate. + + 2008-04-18 Kris Van Hees <kris.van.hees@oracle.com> + +@@ -3677,7 +3814,7 @@ + + 2003-12-15 Brendan Kehoe <brendan@zen.org> + +- * libiberty/Makefile.in (floatformat.o): Add dependency on ++ * Makefile.in (floatformat.o): Add dependency on + config.h to accompany change of 2003-12-03. + + 2003-12-15 Ian Lance Taylor <ian@wasabisystems.com> +@@ -4373,7 +4510,7 @@ + + 2002-10-06 Andreas Jaeger <aj@suse.de> + +- * libiberty/cplus-dem.c (ada_demangle): Get rid of unneeded ++ * cplus-dem.c (ada_demangle): Get rid of unneeded + variable and of strict-aliasing warning. + (grow_vect): Use char as first parameter. + +@@ -4641,7 +4778,7 @@ + + 2002-01-31 Adam Megacz <adam@xwt.org> + +- * gcc/libiberty/configure.in: Treat mingw the same as cywin ++ * configure.in: Treat mingw the same as cywin + wrt HAVE_SYS_ERRLIST. + + 2002-01-30 Phil Edwards <pme@gcc.gnu.org> +@@ -5149,8 +5286,8 @@ Tue Aug 21 12:35:04 2001 Christopher Fa + 2001-03-10 Neil Booth <neil@daikokuya.demon.co.uk> + John David Anglin <dave@hiauly1.hia.nrc.ca> + +- * libiberty/lbasename.c: New file. +- * libiberty/Makefile.in: Update for lbasename. ++ * lbasename.c: New file. ++ * Makefile.in: Update for lbasename. + + 2001-03-06 Zack Weinberg <zackw@stanford.edu> + +@@ -5523,13 +5660,13 @@ Tue Aug 21 12:35:04 2001 Christopher Fa + + 2000-08-24 Greg McGary <greg@mcgary.org> + +- * libiberty/random.c (end_ptr): Revert previous change. ++ * random.c (end_ptr): Revert previous change. + + 2000-08-24 Greg McGary <greg@mcgary.org> + +- * libiberty/cplus-dem.c (cplus_demangle_opname, cplus_mangle_opname, ++ * cplus-dem.c (cplus_demangle_opname, cplus_mangle_opname, + demangle_expression, demangle_function_name): Use ARRAY_SIZE. +- * libiberty/random.c (end_ptr): Likewise. ++ * random.c (end_ptr): Likewise. + + 2000-08-23 Alex Samuel <samuel@codesourcery.com> + +Index: b/src/libiberty/configure +=================================================================== +--- a/src/libiberty/configure ++++ b/src/libiberty/configure +@@ -4398,7 +4398,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu + ac_libiberty_warn_cflags= + save_CFLAGS="$CFLAGS" + for real_option in -W -Wall -Wwrite-strings -Wc++-compat \ +- -Wstrict-prototypes; do ++ -Wstrict-prototypes \ ++ -Wshadow=local; do + # Do the check with the no- prefix removed since gcc silently + # accepts any -Wno-* option on purpose + case $real_option in +@@ -5145,8 +5146,7 @@ case "${host}" in + PICFLAG=-fpic + ;; + # FIXME: Simplify to sh*-*-netbsd*? +- sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \ +- sh64-*-netbsd* | sh64l*-*-netbsd*) ++ sh-*-netbsdelf* | shl*-*-netbsdelf*) + PICFLAG=-fpic + ;; + # Default to -fPIC unless specified otherwise. +Index: b/src/libiberty/configure.ac +=================================================================== +--- a/src/libiberty/configure.ac ++++ b/src/libiberty/configure.ac +@@ -160,7 +160,8 @@ AC_SYS_LARGEFILE + AC_PROG_CPP_WERROR + + ACX_PROG_CC_WARNING_OPTS([-W -Wall -Wwrite-strings -Wc++-compat \ +- -Wstrict-prototypes], [ac_libiberty_warn_cflags]) ++ -Wstrict-prototypes \ ++ -Wshadow=local], [ac_libiberty_warn_cflags]) + ACX_PROG_CC_WARNING_ALMOST_PEDANTIC([], [ac_libiberty_warn_cflags]) + + AC_PROG_CC_C_O +Index: b/src/libiberty/cp-demangle.c +=================================================================== +--- a/src/libiberty/cp-demangle.c ++++ b/src/libiberty/cp-demangle.c +@@ -439,6 +439,8 @@ static struct demangle_component *d_oper + + static struct demangle_component *d_special_name (struct d_info *); + ++static struct demangle_component *d_parmlist (struct d_info *); ++ + static int d_call_offset (struct d_info *, int); + + static struct demangle_component *d_ctor_dtor_name (struct d_info *); +@@ -562,6 +564,32 @@ static int d_demangle_callback (const ch + demangle_callbackref, void *); + static char *d_demangle (const char *, int, size_t *); + ++/* True iff TYPE is a demangling component representing a ++ function-type-qualifier. */ ++ ++static int ++is_fnqual_component_type (enum demangle_component_type type) ++{ ++ return (type == DEMANGLE_COMPONENT_RESTRICT_THIS ++ || type == DEMANGLE_COMPONENT_VOLATILE_THIS ++ || type == DEMANGLE_COMPONENT_CONST_THIS ++ || type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS ++ || type == DEMANGLE_COMPONENT_TRANSACTION_SAFE ++ || type == DEMANGLE_COMPONENT_NOEXCEPT ++ || type == DEMANGLE_COMPONENT_THROW_SPEC ++ || type == DEMANGLE_COMPONENT_REFERENCE_THIS); ++} ++ ++#define FNQUAL_COMPONENT_CASE \ ++ case DEMANGLE_COMPONENT_RESTRICT_THIS: \ ++ case DEMANGLE_COMPONENT_VOLATILE_THIS: \ ++ case DEMANGLE_COMPONENT_CONST_THIS: \ ++ case DEMANGLE_COMPONENT_REFERENCE_THIS: \ ++ case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: \ ++ case DEMANGLE_COMPONENT_TRANSACTION_SAFE: \ ++ case DEMANGLE_COMPONENT_NOEXCEPT: \ ++ case DEMANGLE_COMPONENT_THROW_SPEC ++ + #ifdef CP_DEMANGLE_DEBUG + + static void +@@ -987,14 +1015,9 @@ d_make_comp (struct d_info *di, enum dem + case DEMANGLE_COMPONENT_RESTRICT: + case DEMANGLE_COMPONENT_VOLATILE: + case DEMANGLE_COMPONENT_CONST: +- case DEMANGLE_COMPONENT_RESTRICT_THIS: +- case DEMANGLE_COMPONENT_VOLATILE_THIS: +- case DEMANGLE_COMPONENT_CONST_THIS: +- case DEMANGLE_COMPONENT_TRANSACTION_SAFE: +- case DEMANGLE_COMPONENT_REFERENCE_THIS: +- case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: + case DEMANGLE_COMPONENT_ARGLIST: + case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: ++ FNQUAL_COMPONENT_CASE: + break; + + /* Other types should not be seen here. */ +@@ -1228,12 +1251,7 @@ has_return_type (struct demangle_compone + return 0; + case DEMANGLE_COMPONENT_TEMPLATE: + return ! is_ctor_dtor_or_conversion (d_left (dc)); +- case DEMANGLE_COMPONENT_RESTRICT_THIS: +- case DEMANGLE_COMPONENT_VOLATILE_THIS: +- case DEMANGLE_COMPONENT_CONST_THIS: +- case DEMANGLE_COMPONENT_REFERENCE_THIS: +- case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: +- case DEMANGLE_COMPONENT_TRANSACTION_SAFE: ++ FNQUAL_COMPONENT_CASE: + return has_return_type (d_left (dc)); + } + } +@@ -1290,13 +1308,12 @@ d_encoding (struct d_info *di, int top_l + while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS + || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS + || dc->type == DEMANGLE_COMPONENT_CONST_THIS +- || dc->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE + || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS + || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) + dc = d_left (dc); + + /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then +- there may be CV-qualifiers on its right argument which ++ there may be function-qualifiers on its right argument which + really apply here; this happens when parsing a class + which is local to a function. */ + if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME) +@@ -1304,12 +1321,7 @@ d_encoding (struct d_info *di, int top_l + struct demangle_component *dcr; + + dcr = d_right (dc); +- while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS +- || dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS +- || dcr->type == DEMANGLE_COMPONENT_CONST_THIS +- || dcr->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE +- || dcr->type == DEMANGLE_COMPONENT_REFERENCE_THIS +- || dcr->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) ++ while (is_fnqual_component_type (dcr->type)) + dcr = d_left (dcr); + dc->u.s_binary.right = dcr; + } +@@ -2171,6 +2183,13 @@ d_ctor_dtor_name (struct d_info *di) + case 'C': + { + enum gnu_v3_ctor_kinds kind; ++ int inheriting = 0; ++ ++ if (d_peek_next_char (di) == 'I') ++ { ++ inheriting = 1; ++ d_advance (di, 1); ++ } + + switch (d_peek_next_char (di)) + { +@@ -2192,7 +2211,12 @@ d_ctor_dtor_name (struct d_info *di) + default: + return NULL; + } ++ + d_advance (di, 2); ++ ++ if (inheriting) ++ cplus_demangle_type (di); ++ + return d_make_ctor (di, kind, di->last_name); + } + +@@ -2230,6 +2254,24 @@ d_ctor_dtor_name (struct d_info *di) + } + } + ++/* True iff we're looking at an order-insensitive type-qualifier, including ++ function-type-qualifiers. */ ++ ++static int ++next_is_type_qual (struct d_info *di) ++{ ++ char peek = d_peek_char (di); ++ if (peek == 'r' || peek == 'V' || peek == 'K') ++ return 1; ++ if (peek == 'D') ++ { ++ peek = d_peek_next_char (di); ++ if (peek == 'x' || peek == 'o' || peek == 'O' || peek == 'w') ++ return 1; ++ } ++ return 0; ++} ++ + /* <type> ::= <builtin-type> + ::= <function-type> + ::= <class-enum-type> +@@ -2315,9 +2357,7 @@ cplus_demangle_type (struct d_info *di) + __vector, and it treats it as order-sensitive when mangling + names. */ + +- peek = d_peek_char (di); +- if (peek == 'r' || peek == 'V' || peek == 'K' +- || (peek == 'D' && d_peek_next_char (di) == 'x')) ++ if (next_is_type_qual (di)) + { + struct demangle_component **pret; + +@@ -2352,6 +2392,7 @@ cplus_demangle_type (struct d_info *di) + + can_subst = 1; + ++ peek = d_peek_char (di); + switch (peek) + { + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': +@@ -2643,10 +2684,10 @@ d_cv_qualifiers (struct d_info *di, + + pstart = pret; + peek = d_peek_char (di); +- while (peek == 'r' || peek == 'V' || peek == 'K' +- || (peek == 'D' && d_peek_next_char (di) == 'x')) ++ while (next_is_type_qual (di)) + { + enum demangle_component_type t; ++ struct demangle_component *right = NULL; + + d_advance (di, 1); + if (peek == 'r') +@@ -2672,12 +2713,41 @@ d_cv_qualifiers (struct d_info *di, + } + else + { +- t = DEMANGLE_COMPONENT_TRANSACTION_SAFE; +- di->expansion += sizeof "transaction_safe"; +- d_advance (di, 1); ++ peek = d_next_char (di); ++ if (peek == 'x') ++ { ++ t = DEMANGLE_COMPONENT_TRANSACTION_SAFE; ++ di->expansion += sizeof "transaction_safe"; ++ } ++ else if (peek == 'o' ++ || peek == 'O') ++ { ++ t = DEMANGLE_COMPONENT_NOEXCEPT; ++ di->expansion += sizeof "noexcept"; ++ if (peek == 'O') ++ { ++ right = d_expression (di); ++ if (right == NULL) ++ return NULL; ++ if (! d_check_char (di, 'E')) ++ return NULL; ++ } ++ } ++ else if (peek == 'w') ++ { ++ t = DEMANGLE_COMPONENT_THROW_SPEC; ++ di->expansion += sizeof "throw"; ++ right = d_parmlist (di); ++ if (right == NULL) ++ return NULL; ++ if (! d_check_char (di, 'E')) ++ return NULL; ++ } ++ else ++ return NULL; + } + +- *pret = d_make_comp (di, t, NULL, NULL); ++ *pret = d_make_comp (di, t, NULL, right); + if (*pret == NULL) + return NULL; + pret = &d_left (*pret); +@@ -3352,6 +3422,8 @@ d_expression_1 (struct d_info *di) + first = d_expression_1 (di); + second = d_expression_1 (di); + third = d_expression_1 (di); ++ if (third == NULL) ++ return NULL; + } + else if (code[0] == 'f') + { +@@ -3359,6 +3431,8 @@ d_expression_1 (struct d_info *di) + first = d_operator_name (di); + second = d_expression_1 (di); + third = d_expression_1 (di); ++ if (third == NULL) ++ return NULL; + } + else if (code[0] == 'n') + { +@@ -3776,7 +3850,7 @@ d_substitution (struct d_info *di, int p + { + const char *s; + int len; +- struct demangle_component *c; ++ struct demangle_component *dc; + + if (p->set_last_name != NULL) + di->last_name = d_make_sub (di, p->set_last_name, +@@ -3792,15 +3866,15 @@ d_substitution (struct d_info *di, int p + len = p->simple_len; + } + di->expansion += len; +- c = d_make_sub (di, s, len); ++ dc = d_make_sub (di, s, len); + if (d_peek_char (di) == 'B') + { + /* If there are ABI tags on the abbreviation, it becomes + a substitution candidate. */ +- c = d_abi_tags (di, c); +- d_add_substitution (di, c); ++ dc = d_abi_tags (di, dc); ++ d_add_substitution (di, dc); + } +- return c; ++ return dc; + } + } + +@@ -3968,6 +4042,8 @@ d_count_templates_scopes (int *num_templ + case DEMANGLE_COMPONENT_REFERENCE_THIS: + case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: + case DEMANGLE_COMPONENT_TRANSACTION_SAFE: ++ case DEMANGLE_COMPONENT_NOEXCEPT: ++ case DEMANGLE_COMPONENT_THROW_SPEC: + case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: + case DEMANGLE_COMPONENT_POINTER: + case DEMANGLE_COMPONENT_COMPLEX: +@@ -4163,8 +4239,12 @@ cplus_demangle_print_callback (int optio + + { + #ifdef CP_DYNAMIC_ARRAYS +- __extension__ struct d_saved_scope scopes[dpi.num_saved_scopes]; +- __extension__ struct d_print_template temps[dpi.num_copy_templates]; ++ /* Avoid zero-length VLAs, which are prohibited by the C99 standard ++ and flagged as errors by Address Sanitizer. */ ++ __extension__ struct d_saved_scope scopes[(dpi.num_saved_scopes > 0) ++ ? dpi.num_saved_scopes : 1]; ++ __extension__ struct d_print_template temps[(dpi.num_copy_templates > 0) ++ ? dpi.num_copy_templates : 1]; + + dpi.saved_scopes = scopes; + dpi.copy_templates = temps; +@@ -4492,7 +4572,7 @@ d_maybe_print_fold_expression (struct d_ + + static void + d_print_comp_inner (struct d_print_info *dpi, int options, +- const struct demangle_component *dc) ++ const struct demangle_component *dc) + { + /* Magic variable to let reference smashing skip over the next modifier + without needing to modify *dc. */ +@@ -4579,12 +4659,7 @@ d_print_comp_inner (struct d_print_info + adpm[i].templates = dpi->templates; + ++i; + +- if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS +- && typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS +- && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS +- && typed_name->type != DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS +- && typed_name->type != DEMANGLE_COMPONENT_TRANSACTION_SAFE +- && typed_name->type != DEMANGLE_COMPONENT_REFERENCE_THIS) ++ if (!is_fnqual_component_type (typed_name->type)) + break; + + typed_name = d_left (typed_name); +@@ -4621,13 +4696,7 @@ d_print_comp_inner (struct d_print_info + d_print_error (dpi); + return; + } +- while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS +- || local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS +- || local_name->type == DEMANGLE_COMPONENT_CONST_THIS +- || local_name->type == DEMANGLE_COMPONENT_REFERENCE_THIS +- || local_name->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE +- || (local_name->type +- == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)) ++ while (is_fnqual_component_type (local_name->type)) + { + if (i >= sizeof adpm / sizeof adpm[0]) + { +@@ -4961,16 +5030,11 @@ d_print_comp_inner (struct d_print_info + } + /* Fall through. */ + +- case DEMANGLE_COMPONENT_RESTRICT_THIS: +- case DEMANGLE_COMPONENT_VOLATILE_THIS: +- case DEMANGLE_COMPONENT_CONST_THIS: +- case DEMANGLE_COMPONENT_REFERENCE_THIS: +- case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: + case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: + case DEMANGLE_COMPONENT_POINTER: + case DEMANGLE_COMPONENT_COMPLEX: + case DEMANGLE_COMPONENT_IMAGINARY: +- case DEMANGLE_COMPONENT_TRANSACTION_SAFE: ++ FNQUAL_COMPONENT_CASE: + modifier: + { + /* We keep a list of modifiers on the stack. */ +@@ -5679,13 +5743,7 @@ d_print_mod_list (struct d_print_info *d + + if (mods->printed + || (! suffix +- && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS +- || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS +- || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS +- || mods->mod->type == DEMANGLE_COMPONENT_REFERENCE_THIS +- || mods->mod->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE +- || (mods->mod->type +- == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)))) ++ && (is_fnqual_component_type (mods->mod->type)))) + { + d_print_mod_list (dpi, options, mods->next, suffix); + return; +@@ -5738,12 +5796,7 @@ d_print_mod_list (struct d_print_info *d + dc = dc->u.s_unary_num.sub; + } + +- while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS +- || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS +- || dc->type == DEMANGLE_COMPONENT_CONST_THIS +- || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS +- || dc->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE +- || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) ++ while (is_fnqual_component_type (dc->type)) + dc = d_left (dc); + + d_print_comp (dpi, options, dc); +@@ -5782,6 +5835,24 @@ d_print_mod (struct d_print_info *dpi, i + case DEMANGLE_COMPONENT_TRANSACTION_SAFE: + d_append_string (dpi, " transaction_safe"); + return; ++ case DEMANGLE_COMPONENT_NOEXCEPT: ++ d_append_string (dpi, " noexcept"); ++ if (d_right (mod)) ++ { ++ d_append_char (dpi, '('); ++ d_print_comp (dpi, options, d_right (mod)); ++ d_append_char (dpi, ')'); ++ } ++ return; ++ case DEMANGLE_COMPONENT_THROW_SPEC: ++ d_append_string (dpi, " throw"); ++ if (d_right (mod)) ++ { ++ d_append_char (dpi, '('); ++ d_print_comp (dpi, options, d_right (mod)); ++ d_append_char (dpi, ')'); ++ } ++ return; + case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: + d_append_char (dpi, ' '); + d_print_comp (dpi, options, d_right (mod)); +@@ -5794,11 +5865,13 @@ d_print_mod (struct d_print_info *dpi, i + case DEMANGLE_COMPONENT_REFERENCE_THIS: + /* For the ref-qualifier, put a space before the &. */ + d_append_char (dpi, ' '); ++ /* FALLTHRU */ + case DEMANGLE_COMPONENT_REFERENCE: + d_append_char (dpi, '&'); + return; + case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: + d_append_char (dpi, ' '); ++ /* FALLTHRU */ + case DEMANGLE_COMPONENT_RVALUE_REFERENCE: + d_append_string (dpi, "&&"); + return; +@@ -5867,12 +5940,7 @@ d_print_function_type (struct d_print_in + need_space = 1; + need_paren = 1; + break; +- case DEMANGLE_COMPONENT_RESTRICT_THIS: +- case DEMANGLE_COMPONENT_VOLATILE_THIS: +- case DEMANGLE_COMPONENT_CONST_THIS: +- case DEMANGLE_COMPONENT_REFERENCE_THIS: +- case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: +- case DEMANGLE_COMPONENT_TRANSACTION_SAFE: ++ FNQUAL_COMPONENT_CASE: + break; + default: + break; +@@ -6414,7 +6482,6 @@ is_ctor_or_dtor (const char *mangled, + case DEMANGLE_COMPONENT_CONST_THIS: + case DEMANGLE_COMPONENT_REFERENCE_THIS: + case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: +- case DEMANGLE_COMPONENT_TRANSACTION_SAFE: + default: + dc = NULL; + break; +Index: b/src/libiberty/cplus-dem.c +=================================================================== +--- a/src/libiberty/cplus-dem.c ++++ b/src/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) +@@ -244,6 +247,7 @@ typedef enum type_kind_t + tk_none, + tk_pointer, + tk_reference, ++ tk_rvalue_reference, + tk_integral, + tk_bool, + tk_char, +@@ -319,6 +323,12 @@ const struct demangler_engine libiberty_ + } + , + { ++ RUST_DEMANGLING_STYLE_STRING, ++ rust_demangling, ++ "Rust style demangling" ++ } ++ , ++ { + NULL, unknown_demangling, NULL + } + }; +@@ -435,6 +445,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 *); +@@ -866,10 +880,26 @@ cplus_demangle (const char *mangled, int + work->options |= (int) current_demangling_style & DMGL_STYLE_MASK; + + /* The V3 ABI demangling is implemented elsewhere. */ +- if (GNU_V3_DEMANGLING || AUTO_DEMANGLING) ++ if (GNU_V3_DEMANGLING || RUST_DEMANGLING || AUTO_DEMANGLING) + { + ret = cplus_demangle_v3 (mangled, work->options); +- if (ret || GNU_V3_DEMANGLING) ++ if (GNU_V3_DEMANGLING) ++ return ret; ++ ++ if (ret) ++ { ++ /* Rust symbols are GNU_V3 mangled plus some extra subtitutions. ++ The subtitutions are always smaller, so do in place changes. */ ++ if (rust_is_mangled (ret)) ++ rust_demangle_sym (ret); ++ else if (RUST_DEMANGLING) ++ { ++ free (ret); ++ ret = NULL; ++ } ++ } ++ ++ if (ret || RUST_DEMANGLING) + return ret; + } + +@@ -895,6 +925,27 @@ cplus_demangle (const char *mangled, int + return (ret); + } + ++char * ++rust_demangle (const char *mangled, int options) ++{ ++ /* Rust symbols are GNU_V3 mangled plus some extra subtitutions. */ ++ char *ret = cplus_demangle_v3 (mangled, options); ++ ++ /* The Rust subtitutions are always smaller, so do in place changes. */ ++ if (ret != NULL) ++ { ++ if (rust_is_mangled (ret)) ++ rust_demangle_sym (ret); ++ else ++ { ++ free (ret); ++ ret = NULL; ++ } ++ } ++ ++ return ret; ++} ++ + /* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */ + + char * +@@ -903,7 +954,7 @@ ada_demangle (const char *mangled, int o + int len0; + const char* p; + char *d; +- char *demangled; ++ char *demangled = NULL; + + /* Discard leading _ada_, which is used for library level subprograms. */ + if (strncmp (mangled, "_ada_", 5) == 0) +@@ -1148,6 +1199,7 @@ ada_demangle (const char *mangled, int o + return demangled; + + unknown: ++ XDELETEVEC (demangled); + len0 = strlen (mangled); + demangled = XNEWVEC (char, len0 + 3); + +@@ -1301,6 +1353,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 +1385,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; ++ } ++ if (work->proctypevec != NULL) + { +- free ((char *) work -> typevec); +- work -> typevec = NULL; +- work -> typevec_size = 0; ++ free (work->proctypevec); ++ work->proctypevec = NULL; ++ work->proctypevec_size = 0; + } + if (work->tmpl_argvec) + { +@@ -1635,12 +1697,13 @@ demangle_signature (struct work_stuff *w + 0); + if (!(work->constructor & 1)) + expect_return_type = 1; +- (*mangled)++; ++ if (!**mangled) ++ success = 0; ++ else ++ (*mangled)++; + break; + } +- else +- /* fall through */ +- {;} ++ /* fall through */ + + default: + if (AUTO_DEMANGLING || GNU_DEMANGLING) +@@ -2042,7 +2105,8 @@ demangle_template_value_parm (struct wor + } + else if (tk == tk_real) + success = demangle_real_value (work, mangled, s); +- else if (tk == tk_pointer || tk == tk_reference) ++ else if (tk == tk_pointer || tk == tk_reference ++ || tk == tk_rvalue_reference) + { + if (**mangled == 'Q') + success = demangle_qualified (work, mangled, s, +@@ -2051,7 +2115,8 @@ demangle_template_value_parm (struct wor + else + { + int symbol_len = consume_count (mangled); +- if (symbol_len == -1) ++ if (symbol_len == -1 ++ || symbol_len > (long) strlen (*mangled)) + return -1; + if (symbol_len == 0) + string_appendn (s, "0", 1); +@@ -2114,6 +2179,8 @@ demangle_template (struct work_stuff *wo + { + int idx; + (*mangled)++; ++ if (**mangled == '\0') ++ return (0); + (*mangled)++; + + idx = consume_count_with_underscores (mangled); +@@ -2958,7 +3025,7 @@ gnu_special (struct work_stuff *work, co + int success = 1; + const char *p; + +- if ((*mangled)[0] == '_' ++ if ((*mangled)[0] == '_' && (*mangled)[1] != '\0' + && strchr (cplus_markers, (*mangled)[1]) != NULL + && (*mangled)[2] == '_') + { +@@ -2972,7 +3039,7 @@ gnu_special (struct work_stuff *work, co + && (*mangled)[3] == 't' + && (*mangled)[4] == '_') + || ((*mangled)[1] == 'v' +- && (*mangled)[2] == 't' ++ && (*mangled)[2] == 't' && (*mangled)[3] != '\0' + && strchr (cplus_markers, (*mangled)[3]) != NULL))) + { + /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>" +@@ -3552,6 +3619,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 +3633,7 @@ do_type (struct work_stuff *work, const + + done = 0; + success = 1; ++ is_proctypevec = 0; + while (success && !done) + { + int member; +@@ -3588,6 +3658,14 @@ do_type (struct work_stuff *work, const + tk = tk_reference; + break; + ++ /* An rvalue reference type */ ++ case 'O': ++ (*mangled)++; ++ string_prepend (&decl, "&&"); ++ if (tk == tk_none) ++ tk = tk_rvalue_reference; ++ break; ++ + /* An array */ + case 'A': + { +@@ -3611,13 +3689,20 @@ do_type (struct work_stuff *work, const + /* A back reference to a previously seen type */ + case 'T': + (*mangled)++; +- if (!get_count (mangled, &n) || n >= work -> ntypes) ++ if (!get_count (mangled, &n) || n < 0 || n >= work -> ntypes) + { + 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; +@@ -3645,7 +3730,6 @@ do_type (struct work_stuff *work, const + break; + + case 'M': +- case 'O': + { + type_quals = TYPE_UNQUALIFIED; + +@@ -3725,11 +3809,12 @@ do_type (struct work_stuff *work, const + break; + } + +- if (*(*mangled)++ != 'F') ++ if (*(*mangled) != 'F') + { + success = 0; + break; + } ++ (*mangled)++; + } + if ((member && !demangle_nested_args (work, mangled, &decl)) + || **mangled != '_') +@@ -3789,7 +3874,7 @@ do_type (struct work_stuff *work, const + /* A back reference to a previously seen squangled type */ + case 'B': + (*mangled)++; +- if (!get_count (mangled, &n) || n >= work -> numb) ++ if (!get_count (mangled, &n) || n < 0 || n >= work -> numb) + success = 0; + else + string_append (result, work->btypevec[n]); +@@ -3840,6 +3925,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); +@@ -3983,6 +4071,7 @@ demangle_fund_type (struct work_stuff *w + success = 0; + break; + } ++ /* fall through */ + case 'I': + (*mangled)++; + if (**mangled == '_') +@@ -4130,7 +4219,8 @@ do_hpacc_template_literal (struct work_s + + literal_len = consume_count (mangled); + +- if (literal_len <= 0) ++ if (literal_len <= 0 ++ || literal_len > (long) strlen (*mangled)) + return 0; + + /* Literal parameters are names of arrays, functions, etc. and the +@@ -4252,6 +4342,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 +4640,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: b/src/libiberty/hashtab.c +=================================================================== +--- a/src/libiberty/hashtab.c ++++ b/src/libiberty/hashtab.c +@@ -962,17 +962,17 @@ iterative_hash (const PTR k_in /* the ke + c += length; + switch(len) /* all the case statements fall through */ + { +- case 11: c+=((hashval_t)k[10]<<24); +- case 10: c+=((hashval_t)k[9]<<16); +- case 9 : c+=((hashval_t)k[8]<<8); ++ case 11: c+=((hashval_t)k[10]<<24); /* fall through */ ++ case 10: c+=((hashval_t)k[9]<<16); /* fall through */ ++ case 9 : c+=((hashval_t)k[8]<<8); /* fall through */ + /* the first byte of c is reserved for the length */ +- case 8 : b+=((hashval_t)k[7]<<24); +- case 7 : b+=((hashval_t)k[6]<<16); +- case 6 : b+=((hashval_t)k[5]<<8); +- case 5 : b+=k[4]; +- case 4 : a+=((hashval_t)k[3]<<24); +- case 3 : a+=((hashval_t)k[2]<<16); +- case 2 : a+=((hashval_t)k[1]<<8); ++ case 8 : b+=((hashval_t)k[7]<<24); /* fall through */ ++ case 7 : b+=((hashval_t)k[6]<<16); /* fall through */ ++ case 6 : b+=((hashval_t)k[5]<<8); /* fall through */ ++ case 5 : b+=k[4]; /* fall through */ ++ case 4 : a+=((hashval_t)k[3]<<24); /* fall through */ ++ case 3 : a+=((hashval_t)k[2]<<16); /* fall through */ ++ case 2 : a+=((hashval_t)k[1]<<8); /* fall through */ + case 1 : a+=k[0]; + /* case 0: nothing left to add */ + } +Index: b/src/libiberty/Makefile.in +=================================================================== +--- a/src/libiberty/Makefile.in ++++ b/src/libiberty/Makefile.in +@@ -146,6 +146,7 @@ CFILES = alloca.c argv.c asprintf.c atex + pex-unix.c pex-win32.c \ + physmem.c putenv.c \ + random.c regex.c rename.c rindex.c \ ++ rust-demangle.c \ + safe-ctype.c setenv.c setproctitle.c sha1.c sigsetmask.c \ + simple-object.c simple-object-coff.c simple-object-elf.c \ + simple-object-mach-o.c simple-object-xcoff.c \ +@@ -183,6 +184,7 @@ REQUIRED_OFILES = \ + ./partition.$(objext) ./pexecute.$(objext) ./physmem.$(objext) \ + ./pex-common.$(objext) ./pex-one.$(objext) \ + ./@pexecute@.$(objext) ./vprintf-support.$(objext) \ ++ ./rust-demangle.$(objext) \ + ./safe-ctype.$(objext) \ + ./simple-object.$(objext) ./simple-object-coff.$(objext) \ + ./simple-object-elf.$(objext) ./simple-object-mach-o.$(objext) \ +@@ -1188,6 +1190,17 @@ $(CONFIGURED_OFILES): stamp-picdir stamp + else true; fi + $(COMPILE.c) $(srcdir)/rindex.c $(OUTPUT_OPTION) + ++./rust-demangle.$(objext): $(srcdir)/rust-demangle.c config.h \ ++ $(INCDIR)/ansidecl.h $(INCDIR)/demangle.h $(INCDIR)/libiberty.h \ ++ $(INCDIR)/safe-ctype.h ++ if [ x"$(PICFLAG)" != x ]; then \ ++ $(COMPILE.c) $(PICFLAG) $(srcdir)/rust-demangle.c -o pic/$@; \ ++ else true; fi ++ if [ x"$(NOASANFLAG)" != x ]; then \ ++ $(COMPILE.c) $(PICFLAG) $(NOASANFLAG) $(srcdir)/rust-demangle.c -o noasan/$@; \ ++ else true; fi ++ $(COMPILE.c) $(srcdir)/rust-demangle.c $(OUTPUT_OPTION) ++ + ./safe-ctype.$(objext): $(srcdir)/safe-ctype.c $(INCDIR)/ansidecl.h \ + $(INCDIR)/safe-ctype.h + if [ x"$(PICFLAG)" != x ]; then \ +Index: b/src/libiberty/make-relative-prefix.c +=================================================================== +--- a/src/libiberty/make-relative-prefix.c ++++ b/src/libiberty/make-relative-prefix.c +@@ -233,6 +233,7 @@ make_relative_prefix_1 (const char *prog + int i, n, common; + int needed_len; + char *ret = NULL, *ptr, *full_progname; ++ char *alloc_ptr = NULL; + + if (progname == NULL || bin_prefix == NULL || prefix == NULL) + return NULL; +@@ -256,7 +257,10 @@ make_relative_prefix_1 (const char *prog + #ifdef HAVE_HOST_EXECUTABLE_SUFFIX + len += strlen (HOST_EXECUTABLE_SUFFIX); + #endif +- nstore = (char *) alloca (len); ++ if (len < MAX_ALLOCA_SIZE) ++ nstore = (char *) alloca (len); ++ else ++ alloc_ptr = nstore = (char *) malloc (len); + + startp = endp = temp; + while (1) +@@ -312,12 +316,12 @@ make_relative_prefix_1 (const char *prog + else + full_progname = strdup (progname); + if (full_progname == NULL) +- return NULL; ++ goto bailout; + + prog_dirs = split_directories (full_progname, &prog_num); + free (full_progname); + if (prog_dirs == NULL) +- return NULL; ++ goto bailout; + + bin_dirs = split_directories (bin_prefix, &bin_num); + if (bin_dirs == NULL) +@@ -395,6 +399,7 @@ make_relative_prefix_1 (const char *prog + free_split_directories (prog_dirs); + free_split_directories (bin_dirs); + free_split_directories (prefix_dirs); ++ free (alloc_ptr); + + return ret; + } +Index: b/src/libiberty/pex-win32.c +=================================================================== +--- a/src/libiberty/pex-win32.c ++++ b/src/libiberty/pex-win32.c +@@ -370,6 +370,8 @@ argv_to_cmdline (char *const *argv) + cmdline_len++; + } + } ++ if (j == 0) ++ needs_quotes = 1; + /* Trailing backslashes also need to be escaped because they will be + followed by the terminating quote. */ + if (needs_quotes) +@@ -394,6 +396,8 @@ argv_to_cmdline (char *const *argv) + break; + } + } ++ if (j == 0) ++ needs_quotes = 1; + + if (needs_quotes) + { +Index: b/src/libiberty/regex.c +=================================================================== +--- a/src/libiberty/regex.c ++++ b/src/libiberty/regex.c +@@ -2493,6 +2493,7 @@ PREFIX(regex_compile) (const char *ARG_P + if ((syntax & RE_BK_PLUS_QM) + || (syntax & RE_LIMITED_OPS)) + goto normal_char; ++ /* Fall through. */ + handle_plus: + case '*': + /* If there is no previous pattern... */ +@@ -6697,6 +6698,7 @@ byte_re_match_2_internal (struct re_patt + { + case jump_n: + is_a_jump_n = true; ++ /* Fall through. */ + case pop_failure_jump: + case maybe_pop_jump: + case jump: +@@ -7125,7 +7127,7 @@ byte_re_match_2_internal (struct re_patt + DEBUG_PRINT1 (" Match => jump.\n"); + goto unconditional_jump; + } +- /* Note fall through. */ ++ /* Fall through. */ + + + /* The end of a simple repeat has a pop_failure_jump back to +@@ -7150,7 +7152,7 @@ byte_re_match_2_internal (struct re_patt + dummy_low_reg, dummy_high_reg, + reg_dummy, reg_dummy, reg_info_dummy); + } +- /* Note fall through. */ ++ /* Fall through. */ + + unconditional_jump: + #ifdef _LIBC +@@ -7453,6 +7455,7 @@ byte_re_match_2_internal (struct re_patt + { + case jump_n: + is_a_jump_n = true; ++ /* Fall through. */ + case maybe_pop_jump: + case pop_failure_jump: + case jump: +@@ -7718,6 +7721,7 @@ PREFIX(common_op_match_null_string_p) (U + + case set_number_at: + p1 += 2 * OFFSET_ADDRESS_SIZE; ++ return false; + + default: + /* All other opcodes mean we cannot match the empty string. */ +Index: b/src/libiberty/rust-demangle.c +=================================================================== +--- /dev/null ++++ b/src/libiberty/rust-demangle.c +@@ -0,0 +1,348 @@ ++/* Demangler for the Rust programming language ++ Copyright 2016 Free Software Foundation, Inc. ++ Written by David Tolnay (dtolnay@gmail.com). ++ ++This file is part of the libiberty library. ++Libiberty is free software; you can redistribute it and/or ++modify it under the terms of the GNU Library General Public ++License as published by the Free Software Foundation; either ++version 2 of the License, or (at your option) any later version. ++ ++In addition to the permissions in the GNU Library General Public ++License, the Free Software Foundation gives you unlimited permission ++to link the compiled version of this file into combinations with other ++programs, and to distribute those combinations without any restriction ++coming from the use of this file. (The Library Public License ++restrictions do apply in other respects; for example, they cover ++modification of the file, and distribution when not linked into a ++combined executable.) ++ ++Libiberty 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 ++Library General Public License for more details. ++ ++You should have received a copy of the GNU Library General Public ++License along with libiberty; see the file COPYING.LIB. ++If not, see <http://www.gnu.org/licenses/>. */ ++ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include "safe-ctype.h" ++ ++#include <sys/types.h> ++#include <string.h> ++#include <stdio.h> ++ ++#ifdef HAVE_STRING_H ++#include <string.h> ++#else ++extern size_t strlen(const char *s); ++extern int strncmp(const char *s1, const char *s2, size_t n); ++extern void *memset(void *s, int c, size_t n); ++#endif ++ ++#include <demangle.h> ++#include "libiberty.h" ++ ++ ++/* Mangled Rust symbols look like this: ++ _$LT$std..sys..fd..FileDesc$u20$as$u20$core..ops..Drop$GT$::drop::hc68340e1baa4987a ++ ++ The original symbol is: ++ <std::sys::fd::FileDesc as core::ops::Drop>::drop ++ ++ The last component of the path is a 64-bit hash in lowercase hex, ++ prefixed with "h". Rust does not have a global namespace between ++ crates, an illusion which Rust maintains by using the hash to ++ distinguish things that would otherwise have the same symbol. ++ ++ Any path component not starting with a XID_Start character is ++ prefixed with "_". ++ ++ The following escape sequences are used: ++ ++ "," => $C$ ++ "@" => $SP$ ++ "*" => $BP$ ++ "&" => $RF$ ++ "<" => $LT$ ++ ">" => $GT$ ++ "(" => $LP$ ++ ")" => $RP$ ++ " " => $u20$ ++ "\"" => $u22$ ++ "'" => $u27$ ++ "+" => $u2b$ ++ ";" => $u3b$ ++ "[" => $u5b$ ++ "]" => $u5d$ ++ "{" => $u7b$ ++ "}" => $u7d$ ++ "~" => $u7e$ ++ ++ A double ".." means "::" and a single "." means "-". ++ ++ The only characters allowed in the mangled symbol are a-zA-Z0-9 and _.:$ */ ++ ++static const char *hash_prefix = "::h"; ++static const size_t hash_prefix_len = 3; ++static const size_t hash_len = 16; ++ ++static int is_prefixed_hash (const char *start); ++static int looks_like_rust (const char *sym, size_t len); ++static int unescape (const char **in, char **out, const char *seq, char value); ++ ++/* INPUT: sym: symbol that has been through C++ (gnu v3) demangling ++ ++ This function looks for the following indicators: ++ ++ 1. The hash must consist of "h" followed by 16 lowercase hex digits. ++ ++ 2. As a sanity check, the hash must use between 5 and 15 of the 16 ++ possible hex digits. This is true of 99.9998% of hashes so once ++ in your life you may see a false negative. The point is to ++ notice path components that could be Rust hashes but are ++ probably not, like "haaaaaaaaaaaaaaaa". In this case a false ++ positive (non-Rust symbol has an important path component ++ removed because it looks like a Rust hash) is worse than a false ++ negative (the rare Rust symbol is not demangled) so this sets ++ the balance in favor of false negatives. ++ ++ 3. There must be no characters other than a-zA-Z0-9 and _.:$ ++ ++ 4. There must be no unrecognized $-sign sequences. ++ ++ 5. There must be no sequence of three or more dots in a row ("..."). */ ++ ++int ++rust_is_mangled (const char *sym) ++{ ++ size_t len, len_without_hash; ++ ++ if (!sym) ++ return 0; ++ ++ len = strlen (sym); ++ if (len <= hash_prefix_len + hash_len) ++ /* Not long enough to contain "::h" + hash + something else */ ++ return 0; ++ ++ len_without_hash = len - (hash_prefix_len + hash_len); ++ if (!is_prefixed_hash (sym + len_without_hash)) ++ return 0; ++ ++ return looks_like_rust (sym, len_without_hash); ++} ++ ++/* A hash is the prefix "::h" followed by 16 lowercase hex digits. The ++ hex digits must comprise between 5 and 15 (inclusive) distinct ++ digits. */ ++ ++static int ++is_prefixed_hash (const char *str) ++{ ++ const char *end; ++ char seen[16]; ++ size_t i; ++ int count; ++ ++ if (strncmp (str, hash_prefix, hash_prefix_len)) ++ return 0; ++ str += hash_prefix_len; ++ ++ memset (seen, 0, sizeof(seen)); ++ for (end = str + hash_len; str < end; str++) ++ if (*str >= '0' && *str <= '9') ++ seen[*str - '0'] = 1; ++ else if (*str >= 'a' && *str <= 'f') ++ seen[*str - 'a' + 10] = 1; ++ else ++ return 0; ++ ++ /* Count how many distinct digits seen */ ++ count = 0; ++ for (i = 0; i < 16; i++) ++ if (seen[i]) ++ count++; ++ ++ return count >= 5 && count <= 15; ++} ++ ++static int ++looks_like_rust (const char *str, size_t len) ++{ ++ const char *end = str + len; ++ ++ while (str < end) ++ switch (*str) ++ { ++ case '$': ++ if (!strncmp (str, "$C$", 3)) ++ str += 3; ++ else if (!strncmp (str, "$SP$", 4) ++ || !strncmp (str, "$BP$", 4) ++ || !strncmp (str, "$RF$", 4) ++ || !strncmp (str, "$LT$", 4) ++ || !strncmp (str, "$GT$", 4) ++ || !strncmp (str, "$LP$", 4) ++ || !strncmp (str, "$RP$", 4)) ++ str += 4; ++ else if (!strncmp (str, "$u20$", 5) ++ || !strncmp (str, "$u22$", 5) ++ || !strncmp (str, "$u27$", 5) ++ || !strncmp (str, "$u2b$", 5) ++ || !strncmp (str, "$u3b$", 5) ++ || !strncmp (str, "$u5b$", 5) ++ || !strncmp (str, "$u5d$", 5) ++ || !strncmp (str, "$u7b$", 5) ++ || !strncmp (str, "$u7d$", 5) ++ || !strncmp (str, "$u7e$", 5)) ++ str += 5; ++ else ++ return 0; ++ break; ++ case '.': ++ /* Do not allow three or more consecutive dots */ ++ if (!strncmp (str, "...", 3)) ++ return 0; ++ /* Fall through */ ++ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': ++ case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': ++ case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': ++ case 's': case 't': case 'u': case 'v': case 'w': case 'x': ++ case 'y': case 'z': ++ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': ++ case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': ++ case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': ++ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': ++ case 'Y': case 'Z': ++ case '0': case '1': case '2': case '3': case '4': case '5': ++ case '6': case '7': case '8': case '9': ++ case '_': ++ case ':': ++ str++; ++ break; ++ default: ++ return 0; ++ } ++ ++ return 1; ++} ++ ++/* ++ INPUT: sym: symbol for which rust_is_mangled(sym) returned 1. ++ ++ The input is demangled in-place because the mangled name is always ++ longer than the demangled one. */ ++ ++void ++rust_demangle_sym (char *sym) ++{ ++ const char *in; ++ char *out; ++ const char *end; ++ ++ if (!sym) ++ return; ++ ++ in = sym; ++ out = sym; ++ end = sym + strlen (sym) - (hash_prefix_len + hash_len); ++ ++ while (in < end) ++ switch (*in) ++ { ++ case '$': ++ if (!(unescape (&in, &out, "$C$", ',') ++ || unescape (&in, &out, "$SP$", '@') ++ || unescape (&in, &out, "$BP$", '*') ++ || unescape (&in, &out, "$RF$", '&') ++ || unescape (&in, &out, "$LT$", '<') ++ || unescape (&in, &out, "$GT$", '>') ++ || unescape (&in, &out, "$LP$", '(') ++ || unescape (&in, &out, "$RP$", ')') ++ || unescape (&in, &out, "$u20$", ' ') ++ || unescape (&in, &out, "$u22$", '\"') ++ || unescape (&in, &out, "$u27$", '\'') ++ || unescape (&in, &out, "$u2b$", '+') ++ || unescape (&in, &out, "$u3b$", ';') ++ || unescape (&in, &out, "$u5b$", '[') ++ || unescape (&in, &out, "$u5d$", ']') ++ || unescape (&in, &out, "$u7b$", '{') ++ || unescape (&in, &out, "$u7d$", '}') ++ || unescape (&in, &out, "$u7e$", '~'))) { ++ /* unexpected escape sequence, not looks_like_rust. */ ++ goto fail; ++ } ++ break; ++ case '_': ++ /* If this is the start of a path component and the next ++ character is an escape sequence, ignore the underscore. The ++ mangler inserts an underscore to make sure the path ++ component begins with a XID_Start character. */ ++ if ((in == sym || in[-1] == ':') && in[1] == '$') ++ in++; ++ else ++ *out++ = *in++; ++ break; ++ case '.': ++ if (in[1] == '.') ++ { ++ /* ".." becomes "::" */ ++ *out++ = ':'; ++ *out++ = ':'; ++ in += 2; ++ } ++ else ++ { ++ /* "." becomes "-" */ ++ *out++ = '-'; ++ in++; ++ } ++ break; ++ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': ++ case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': ++ case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': ++ case 's': case 't': case 'u': case 'v': case 'w': case 'x': ++ case 'y': case 'z': ++ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': ++ case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': ++ case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': ++ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': ++ case 'Y': case 'Z': ++ case '0': case '1': case '2': case '3': case '4': case '5': ++ case '6': case '7': case '8': case '9': ++ case ':': ++ *out++ = *in++; ++ break; ++ default: ++ /* unexpected character in symbol, not looks_like_rust. */ ++ goto fail; ++ } ++ goto done; ++ ++fail: ++ *out++ = '?'; /* This is pretty lame, but it's hard to do better. */ ++done: ++ *out = '\0'; ++} ++ ++static int ++unescape (const char **in, char **out, const char *seq, char value) ++{ ++ size_t len = strlen (seq); ++ ++ if (strncmp (*in, seq, len)) ++ return 0; ++ ++ **out = value; ++ ++ *in += len; ++ *out += 1; ++ ++ return 1; ++} +Index: b/src/libiberty/strndup.c +=================================================================== +--- a/src/libiberty/strndup.c ++++ b/src/libiberty/strndup.c +@@ -33,7 +33,7 @@ memory was available. The result is alw + #include "ansidecl.h" + #include <stddef.h> + +-extern size_t strlen (const char*); ++extern size_t strnlen (const char *s, size_t maxlen); + extern PTR malloc (size_t); + extern PTR memcpy (PTR, const PTR, size_t); + +@@ -41,10 +41,7 @@ char * + strndup (const char *s, size_t n) + { + char *result; +- size_t len = strlen (s); +- +- if (n < len) +- len = n; ++ size_t len = strnlen (s, n); + + result = (char *) malloc (len + 1); + if (!result) +Index: b/src/libiberty/testsuite/demangle-expected +=================================================================== +--- a/src/libiberty/testsuite/demangle-expected ++++ b/src/libiberty/testsuite/demangle-expected +@@ -31,6 +31,11 @@ ArrowLine::ArrowheadIntersects(Arrowhead + ArrowLine::ArrowheadIntersects + # + --format=gnu --no-params ++ArrowheadIntersects__9ArrowLineP9ArrowheadO6BoxObjP7Graphic ++ArrowLine::ArrowheadIntersects(Arrowhead *, BoxObj &&, Graphic *) ++ArrowLine::ArrowheadIntersects ++# ++--format=gnu --no-params + AtEnd__13ivRubberGroup + ivRubberGroup::AtEnd(void) + ivRubberGroup::AtEnd +@@ -51,6 +56,11 @@ TextCode::CoreConstDecls(ostream &) + TextCode::CoreConstDecls + # + --format=gnu --no-params ++CoreConstDecls__8TextCodeO7ostream ++TextCode::CoreConstDecls(ostream &&) ++TextCode::CoreConstDecls ++# ++--format=gnu --no-params + Detach__8StateVarP12StateVarView + StateVar::Detach(StateVarView *) + StateVar::Detach +@@ -66,21 +76,41 @@ RelateManip::Effect(ivEvent &) + RelateManip::Effect + # + --format=gnu --no-params ++Effect__11RelateManipO7ivEvent ++RelateManip::Effect(ivEvent &&) ++RelateManip::Effect ++# ++--format=gnu --no-params + FindFixed__FRP4CNetP4CNet + FindFixed(CNet *&, CNet *) + FindFixed + # + --format=gnu --no-params ++FindFixed__FOP4CNetP4CNet ++FindFixed(CNet *&&, CNet *) ++FindFixed ++# ++--format=gnu --no-params + Fix48_abort__FR8twolongs + Fix48_abort(twolongs &) + Fix48_abort + # + --format=gnu --no-params ++Fix48_abort__FO8twolongs ++Fix48_abort(twolongs &&) ++Fix48_abort ++# ++--format=gnu --no-params + GetBarInfo__15iv2_6_VScrollerP13ivPerspectiveRiT2 + iv2_6_VScroller::GetBarInfo(ivPerspective *, int &, int &) + iv2_6_VScroller::GetBarInfo + # + --format=gnu --no-params ++GetBarInfo__15iv2_6_VScrollerP13ivPerspectiveOiT2 ++iv2_6_VScroller::GetBarInfo(ivPerspective *, int &&, int &&) ++iv2_6_VScroller::GetBarInfo ++# ++--format=gnu --no-params + GetBgColor__C9ivPainter + ivPainter::GetBgColor(void) const + ivPainter::GetBgColor +@@ -986,11 +1016,21 @@ List<VHDLEntity>::Pix::Pix(List<VHDLEnti + List<VHDLEntity>::Pix::Pix + # + --format=gnu --no-params ++__Q2t4List1Z10VHDLEntity3PixOCQ2t4List1Z10VHDLEntity3Pix ++List<VHDLEntity>::Pix::Pix(List<VHDLEntity>::Pix const &&) ++List<VHDLEntity>::Pix::Pix ++# ++--format=gnu --no-params + __Q2t4List1Z10VHDLEntity7elementRC10VHDLEntityPT0 + List<VHDLEntity>::element::element(VHDLEntity const &, List<VHDLEntity>::element *) + List<VHDLEntity>::element::element + # + --format=gnu --no-params ++__Q2t4List1Z10VHDLEntity7elementOC10VHDLEntityPT0 ++List<VHDLEntity>::element::element(VHDLEntity const &&, List<VHDLEntity>::element *) ++List<VHDLEntity>::element::element ++# ++--format=gnu --no-params + __Q2t4List1Z10VHDLEntity7elementRCQ2t4List1Z10VHDLEntity7element + List<VHDLEntity>::element::element(List<VHDLEntity>::element const &) + List<VHDLEntity>::element::element +@@ -1036,6 +1076,11 @@ PixX<VHDLLibrary, VHDLLibraryRep, List<V + PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX + # + --format=gnu --no-params ++__t4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntityOCt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity ++PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX(PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> > const &&) ++PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX ++# ++--format=gnu --no-params + nextE__C11VHDLLibraryRt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity + VHDLLibrary::nextE(PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> > &) const + VHDLLibrary::nextE +@@ -1261,6 +1306,11 @@ smanip_int::smanip_int(ios &(*)(ios &, i + smanip_int::smanip_int + # + --format=lucid --no-params ++__ct__10smanip_intFPFO3iosi_O3iosi ++smanip_int::smanip_int(ios &&(*)(ios &&, int), int) ++smanip_int::smanip_int ++# ++--format=lucid --no-params + __ct__11fstreambaseFi + fstreambase::fstreambase(int) + fstreambase::fstreambase +@@ -1281,6 +1331,11 @@ smanip_long::smanip_long(ios &(*)(ios &, + smanip_long::smanip_long + # + --format=lucid --no-params ++__ct__11smanip_longFPFO3iosl_O3iosl ++smanip_long::smanip_long(ios &&(*)(ios &&, long), long) ++smanip_long::smanip_long ++# ++--format=lucid --no-params + __ct__11stdiostreamFP4FILE + stdiostream::stdiostream(FILE *) + stdiostream::stdiostream +@@ -1321,6 +1376,11 @@ foo::foo(foo &) + foo::foo + # + --format=lucid --no-params ++__ct__3fooFO3foo ++foo::foo(foo &&) ++foo::foo ++# ++--format=lucid --no-params + __ct__3fooFi + foo::foo(int) + foo::foo +@@ -1336,6 +1396,11 @@ foo::foo(int, foo &, int, foo &, int, fo + foo::foo + # + --format=lucid --no-params ++__ct__3fooFiO3fooT1T2T1T2 ++foo::foo(int, foo &&, int, foo &&, int, foo &&) ++foo::foo ++# ++--format=lucid --no-params + __ct__3iosFP9streambuf + ios::ios(streambuf *) + ios::ios +@@ -1811,6 +1876,11 @@ foo(int, foo &, int, foo &, int, foo &) + foo + # + --format=lucid --no-params ++foo__FiO3fooT1T2T1T2 ++foo(int, foo &&, int, foo &&, int, foo &&) ++foo ++# ++--format=lucid --no-params + foo___3barFl + bar::foo_(long) + bar::foo_ +@@ -2561,6 +2631,11 @@ DListNode<RLabel &>::DListNode(RLabel &, + DListNode<RLabel &>::DListNode + # + --format=arm --no-params ++__ct__25DListNode__pt__9_O6RLabelFO6RLabelP25DListNode__pt__9_O6RLabelT2 ++DListNode<RLabel &&>::DListNode(RLabel &&, DListNode<RLabel &&> *, DListNode<RLabel &&> *) ++DListNode<RLabel &&>::DListNode ++# ++--format=arm --no-params + bar__3fooFiT16FooBar + foo::bar(int, int, FooBar) + foo::bar +@@ -2991,6 +3066,11 @@ DListNode<RLabel &>::DListNode(RLabel &, + DListNode<RLabel &>::DListNode + # + --format=hp --no-params ++__ct__9DListNodeXTO6RLabel__FO6RLabelP9DListNodeXTO6RLabel_T2 ++DListNode<RLabel &&>::DListNode(RLabel &&, DListNode<RLabel &&> *, DListNode<RLabel &&> *) ++DListNode<RLabel &&>::DListNode ++# ++--format=hp --no-params + elem__6vectorXTiUP34__Fi + vector<int,34U>::elem(int) + vector<int,34U>::elem +@@ -3021,16 +3101,31 @@ vector<int,-67,4000U,short &>::elem(int) + vector<int,-67,4000U,short &>::elem + # + --format=hp --no-params ++elem__6vectorXTiSN67UP4000TOs__Fi ++vector<int,-67,4000U,short &&>::elem(int) ++vector<int,-67,4000U,short &&>::elem ++# ++--format=hp --no-params + elem__6vectorXTiSN67TRdTFPv_i__Fi + vector<int,-67,double &,int (void *)>::elem(int) + vector<int,-67,double &,int (void *)>::elem + # + --format=hp --no-params ++elem__6vectorXTiSN67TOdTFPv_i__Fi ++vector<int,-67,double &&,int (void *)>::elem(int) ++vector<int,-67,double &&,int (void *)>::elem ++# ++--format=hp --no-params + X__6vectorXTiSN67TdTPvUP5TRs + vector<int,-67,double,void *,5U,short &>::X + vector<int,-67,double,void *,5U,short &>::X + # + --format=hp --no-params ++X__6vectorXTiSN67TdTPvUP5TOs ++vector<int,-67,double,void *,5U,short &&>::X ++vector<int,-67,double,void *,5U,short &&>::X ++# ++--format=hp --no-params + elem__6vectorXTiA3foo__Fi + vector<int,&foo>::elem(int) + vector<int,&foo>::elem +@@ -3071,6 +3166,11 @@ Spec<int,int &,int>::spec(int *) + Spec<int,int &,int>::spec + # + --format=hp --no-params ++spec__17Spec<#1,#1.&&,#1>XTiTOiTi_FPi ++Spec<int,int &&,int>::spec(int *) ++Spec<int,int &&,int>::spec ++# ++--format=hp --no-params + add__XTc_FcT1 + add<char>(char, char) + add<char> +@@ -3101,6 +3201,11 @@ C<Test, Test::output> call<Test>(Test &) + C<Test, Test::output> call<Test> + # + --format=gnu --no-params ++call__H1Z4Test_OX01_t1C2ZX01PMX01FPX01i_vQ2X016output ++C<Test, Test::output> call<Test>(Test &&) ++C<Test, Test::output> call<Test> ++# ++--format=gnu --no-params + fn__FPQ21n1cPMQ21n1cFPQ21n1c_i + fn(n::c *, int (n::c::*)(n::c *)) + fn +@@ -3126,6 +3231,11 @@ int foo<TA<int const &, NA<9> > >(TA<int + int foo<TA<int const &, NA<9> > > + # + --format=gnu --no-params ++foo__H1Zt2TA2ZOCiZt2NA1Ui9_X01_i ++int foo<TA<int const &&, NA<9> > >(TA<int const &&, NA<9> >) ++int foo<TA<int const &&, NA<9> > > ++# ++--format=gnu --no-params + foo__H1Zt2TA2ZcZt2NA1Ui20_X01_i + int foo<TA<char, NA<20> > >(TA<char, NA<20> >) + int foo<TA<char, NA<20> > > +@@ -3402,6 +3512,11 @@ int* const volatile restrict _far + _Z3fooILi2EEvRAplT_Li1E_i + void foo<2>(int (&) [(2)+(1)]) + foo<2> ++# ++--format=gnu-v3 --no-params ++_Z3fooILi2EEvOAplT_Li1E_i ++void foo<2>(int (&&) [(2)+(1)]) ++foo<2> + # + --format=gnu-v3 --no-params + _Z1fM1AKFvvE +@@ -4462,6 +4577,66 @@ __vt_90000000000cafebabe + + _Z80800000000000000000000 + _Z80800000000000000000000 ++# ++# 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<>) ++ ++# Inheriting constructor ++_ZN1DCI11BEi ++D::B(int) ++ ++# exception-specification (C++17) ++_Z1fIvJiELb0EEvPDOT1_EFT_DpT0_E ++void f<void, int, false>(void (*)(int) noexcept(false)) ++ ++_Z1fIvJiELb0EEvPDoFT_DpT0_E ++void f<void, int, false>(void (*)(int) noexcept) ++ ++_Z1fIvJiELb0EEvPDwiEFT_DpT0_E ++void f<void, int, false>(void (*)(int) throw(int)) ++ ++# Could crash ++_ ++_ ++ ++# Could crash ++_vt ++_vt ++ ++# Could crash ++_$_1Acitz ++_$_1Acitz ++ ++# Could crash ++_$_H1R ++_$_H1R ++ ++# Could crash ++_Q8ccQ4M2e. ++_Q8ccQ4M2e. ++ ++# fold-expression with missing third component could crash. ++_Z12binary_rightIJLi1ELi2ELi3EEEv1AIXfRplT_LiEEE ++_Z12binary_rightIJLi1ELi2ELi3EEEv1AIXfRplT_LiEEE ++ ++# ?: expression with missing third component could crash. ++AquT_quT_4mxautouT_4mxxx ++AquT_quT_4mxautouT_4mxxx + + # pr c++/78252 generic lambda mangling uses template parms, and leads + # to unbounded recursion if not dealt with properly +Index: b/src/libiberty/testsuite/Makefile.in +=================================================================== +--- a/src/libiberty/testsuite/Makefile.in ++++ b/src/libiberty/testsuite/Makefile.in +@@ -45,8 +45,8 @@ all: + # CHECK is set to "really_check" or the empty string by configure. + check: @CHECK@ + +-really-check: check-cplus-dem check-d-demangle check-pexecute check-expandargv \ +- check-strtol ++really-check: check-cplus-dem check-d-demangle check-rust-demangle \ ++ check-pexecute check-expandargv check-strtol + + # Run some tests of the demangler. + check-cplus-dem: test-demangle $(srcdir)/demangle-expected +@@ -55,6 +55,9 @@ check-cplus-dem: test-demangle $(srcdir) + check-d-demangle: test-demangle $(srcdir)/d-demangle-expected + ./test-demangle < $(srcdir)/d-demangle-expected + ++check-rust-demangle: test-demangle $(srcdir)/rust-demangle-expected ++ ./test-demangle < $(srcdir)/rust-demangle-expected ++ + # Check the pexecute code. + check-pexecute: test-pexecute + ./test-pexecute +Index: b/src/libiberty/testsuite/rust-demangle-expected +=================================================================== +--- /dev/null ++++ b/src/libiberty/testsuite/rust-demangle-expected +@@ -0,0 +1,161 @@ ++# This file holds test cases for the Rust demangler. ++# Each test case looks like this: ++# options ++# input to be demangled ++# expected output ++# ++# See demangle-expected for documentation of supported options. ++# ++# A line starting with `#' is ignored. ++# However, blank lines in this file are NOT ignored. ++# ++############ ++# ++# Coverage Tests ++# ++# ++# Demangles as rust symbol. ++--format=rust ++_ZN4main4main17he714a2e23ed7db23E ++main::main ++# Also demangles as c++ gnu v3 mangled symbol. But with extra Rust hash. ++--format=gnu-v3 ++_ZN4main4main17he714a2e23ed7db23E ++main::main::he714a2e23ed7db23 ++# But auto should demangle fully gnu-v3 -> rust -> demangled, not partially. ++--format=auto ++_ZN4main4main17he714a2e23ed7db23E ++main::main ++# Hash is exactly 16 hex chars. Not more. ++--format=auto ++_ZN4main4main18h1e714a2e23ed7db23E ++main::main::h1e714a2e23ed7db23 ++# Not less. ++--format=auto ++_ZN4main4main16h714a2e23ed7db23E ++main::main::h714a2e23ed7db23 ++# And not non-hex. ++--format=auto ++_ZN4main4main17he714a2e23ed7db2gE ++main::main::he714a2e23ed7db2g ++# $XX$ substitutions should not contain just numbers. ++--format=auto ++_ZN4main4$99$17he714a2e23ed7db23E ++main::$99$::he714a2e23ed7db23 ++# _ at start of path should be removed. ++# ".." translates to "::" "$GT$" to ">" and "$LT$" to "<". ++--format=rust ++_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3bar17h930b740aa94f1d3aE ++<Test + 'static as foo::Bar<Test>>::bar ++# ++--format=rust ++_ZN54_$LT$I$u20$as$u20$core..iter..traits..IntoIterator$GT$9into_iter17h8581507801fb8615E ++<I as core::iter::traits::IntoIterator>::into_iter ++# ++--format=rust ++_ZN10parse_tsan4main17hdbbfdf1c6a7e27d9E ++parse_tsan::main ++# ++--format=rust ++_ZN65_$LT$std..env..Args$u20$as$u20$core..iter..iterator..Iterator$GT$4next17h420a7c8d0c7eef40E ++<std::env::Args as core::iter::iterator::Iterator>::next ++# ++--format=rust ++_ZN4core3str9from_utf817hdcea28871313776dE ++core::str::from_utf8 ++# ++--format=rust ++_ZN4core3mem7size_of17h18bde9bb8c22e2cfE ++core::mem::size_of ++# ++--format=rust ++_ZN5alloc4heap8allocate17hd55c03e6cb81d924E ++alloc::heap::allocate ++# ++--format=rust ++_ZN4core3ptr8null_mut17h736cce09ca0ac11aE ++core::ptr::null_mut ++# ++--format=rust ++_ZN4core3ptr31_$LT$impl$u20$$BP$mut$u20$T$GT$7is_null17h7f9de798bc3f0879E ++core::ptr::<impl *mut T>::is_null ++# ++--format=rust ++_ZN40_$LT$alloc..raw_vec..RawVec$LT$T$GT$$GT$6double17h4166e2b47539e1ffE ++<alloc::raw_vec::RawVec<T>>::double ++# ++--format=rust ++_ZN39_$LT$collections..vec..Vec$LT$T$GT$$GT$4push17hd4b6b23c1b88141aE ++<collections::vec::Vec<T>>::push ++# ++--format=rust ++_ZN70_$LT$collections..vec..Vec$LT$T$GT$$u20$as$u20$core..ops..DerefMut$GT$9deref_mut17hf299b860dc5a831cE ++<collections::vec::Vec<T> as core::ops::DerefMut>::deref_mut ++# ++--format=rust ++_ZN63_$LT$core..ptr..Unique$LT$T$GT$$u20$as$u20$core..ops..Deref$GT$5deref17hc784b4a166cb5e5cE ++<core::ptr::Unique<T> as core::ops::Deref>::deref ++# ++--format=rust ++_ZN40_$LT$alloc..raw_vec..RawVec$LT$T$GT$$GT$3ptr17h7570b6e9070b693bE ++<alloc::raw_vec::RawVec<T>>::ptr ++# ++--format=rust ++_ZN4core3ptr31_$LT$impl$u20$$BP$mut$u20$T$GT$7is_null17h0f3228f343444ac8E ++core::ptr::<impl *mut T>::is_null ++# ++--format=rust ++_ZN53_$LT$$u5b$T$u5d$$u20$as$u20$core..slice..SliceExt$GT$10as_mut_ptr17h153241df1c7d1666E ++<[T] as core::slice::SliceExt>::as_mut_ptr ++# ++--format=rust ++_ZN11collections5slice29_$LT$impl$u20$$u5b$T$u5d$$GT$10as_mut_ptr17hf12a6d0409938c96E ++collections::slice::<impl [T]>::as_mut_ptr ++# ++--format=rust ++_ZN4core3ptr5write17h651fe53ec860e780E ++core::ptr::write ++# ++--format=rust ++_ZN65_$LT$std..env..Args$u20$as$u20$core..iter..iterator..Iterator$GT$4next17h420a7c8d0c7eef40E ++<std::env::Args as core::iter::iterator::Iterator>::next ++# ++--format=rust ++_ZN54_$LT$I$u20$as$u20$core..iter..traits..IntoIterator$GT$9into_iter17he06cb713aae5b465E ++<I as core::iter::traits::IntoIterator>::into_iter ++# ++--format=rust ++_ZN71_$LT$collections..vec..IntoIter$LT$T$GT$$u20$as$u20$core..ops..Drop$GT$4drop17hf7f23304ebe62eedE ++<collections::vec::IntoIter<T> as core::ops::Drop>::drop ++# ++--format=rust ++_ZN86_$LT$collections..vec..IntoIter$LT$T$GT$$u20$as$u20$core..iter..iterator..Iterator$GT$4next17h04b3fbf148c39713E ++<collections::vec::IntoIter<T> as core::iter::iterator::Iterator>::next ++# ++--format=rust ++_ZN75_$LT$$RF$$u27$a$u20$mut$u20$I$u20$as$u20$core..iter..iterator..Iterator$GT$4next17ha050492063e0fd20E ++<&'a mut I as core::iter::iterator::Iterator>::next ++# Different hashes are OK, they are just stripped. ++--format=rust ++_ZN13drop_contents17hfe3c0a68c8ad1c74E ++drop_contents ++# ++--format=rust ++_ZN13drop_contents17h48cb59bef15bb555E ++drop_contents ++# ++--format=rust ++_ZN4core3mem7size_of17h900b33157bf58f26E ++core::mem::size_of ++# ++--format=rust ++_ZN67_$LT$alloc..raw_vec..RawVec$LT$T$GT$$u20$as$u20$core..ops..Drop$GT$4drop17h96a5cf6e94807905E ++<alloc::raw_vec::RawVec<T> as core::ops::Drop>::drop ++# ++--format=rust ++_ZN68_$LT$core..nonzero..NonZero$LT$T$GT$$u20$as$u20$core..ops..Deref$GT$5deref17hc49056f882aa46dbE ++<core::nonzero::NonZero<T> as core::ops::Deref>::deref ++# ++--format=rust ++_ZN63_$LT$core..ptr..Unique$LT$T$GT$$u20$as$u20$core..ops..Deref$GT$5deref17h19f2ad4920655e85E ++<core::ptr::Unique<T> as core::ops::Deref>::deref +Index: b/src/libiberty/testsuite/test-pexecute.c +=================================================================== +--- a/src/libiberty/testsuite/test-pexecute.c ++++ b/src/libiberty/testsuite/test-pexecute.c +@@ -285,6 +285,20 @@ main (int argc, char **argv) + ERROR ("echo exit status failed"); + pex_free (pex1); + ++ /* Check empty parameters don't get lost. */ ++ pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp"); ++ subargv[1] = "echo"; ++ subargv[2] = "foo"; ++ subargv[3] = ""; ++ subargv[4] = "bar"; ++ subargv[5] = NULL; ++ TEST_PEX_RUN (pex1, 0, "./test-pexecute", subargv, NULL, NULL); ++ e = TEST_PEX_READ_OUTPUT (pex1); ++ CHECK_LINE (e, "foo bar"); /* Two spaces! */ ++ if (TEST_PEX_GET_STATUS_1 (pex1) != 0) ++ ERROR ("echo exit status failed"); ++ pex_free (pex1); ++ + pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp"); + subargv[1] = "echo"; + subargv[2] = "bar"; +Index: b/src/libiberty/xmemdup.c +=================================================================== +--- a/src/libiberty/xmemdup.c ++++ b/src/libiberty/xmemdup.c +@@ -1,4 +1,4 @@ +-/* xmemdup.c -- Duplicate a memory buffer, using xcalloc. ++/* xmemdup.c -- Duplicate a memory buffer, using xmalloc. + This trivial function is in the public domain. + Jeff Garzik, September 1999. */ + +@@ -34,6 +34,8 @@ allocated, the remaining memory is zeroe + PTR + xmemdup (const PTR input, size_t copy_size, size_t alloc_size) + { +- PTR output = xcalloc (1, alloc_size); ++ PTR output = xmalloc (alloc_size); ++ if (alloc_size > copy_size) ++ memset ((char *) output + copy_size, 0, alloc_size - copy_size); + return (PTR) memcpy (output, input, copy_size); + } +Index: b/src/libiberty/xstrndup.c +=================================================================== +--- a/src/libiberty/xstrndup.c ++++ b/src/libiberty/xstrndup.c +@@ -48,10 +48,7 @@ char * + xstrndup (const char *s, size_t n) + { + char *result; +- size_t len = strlen (s); +- +- if (n < len) +- len = n; ++ size_t len = strnlen (s, n); + + result = XNEWVEC (char, len + 1); + +Index: b/src/include/libiberty.h +=================================================================== +--- a/src/include/libiberty.h ++++ b/src/include/libiberty.h +@@ -397,6 +397,17 @@ extern void hex_init (void); + /* Save files used for communication between processes. */ + #define PEX_SAVE_TEMPS 0x4 + ++/* Max number of alloca bytes per call before we must switch to malloc. ++ ++ ?? Swiped from gnulib's regex_internal.h header. Is this actually ++ the case? This number seems arbitrary, though sane. ++ ++ The OS usually guarantees only one guard page at the bottom of the stack, ++ and a page size can be as small as 4096 bytes. So we cannot safely ++ allocate anything larger than 4096 bytes. Also care for the possibility ++ of a few compiler-allocated temporary stack slots. */ ++#define MAX_ALLOCA_SIZE 4032 ++ + /* Prepare to execute one or more programs, with standard output of + each program fed to standard input of the next. + FLAGS As above. +Index: b/src/include/demangle.h +=================================================================== +--- a/src/include/demangle.h ++++ b/src/include/demangle.h +@@ -63,9 +63,10 @@ extern "C" { + #define DMGL_GNU_V3 (1 << 14) + #define DMGL_GNAT (1 << 15) + #define DMGL_DLANG (1 << 16) ++#define DMGL_RUST (1 << 17) /* Rust wraps GNU_V3 style mangling. */ + + /* If none of these are set, use 'current_demangling_style' as the default. */ +-#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG) ++#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG|DMGL_RUST) + + /* Enumeration of possible demangling styles. + +@@ -88,7 +89,8 @@ extern enum demangling_styles + gnu_v3_demangling = DMGL_GNU_V3, + java_demangling = DMGL_JAVA, + gnat_demangling = DMGL_GNAT, +- dlang_demangling = DMGL_DLANG ++ dlang_demangling = DMGL_DLANG, ++ rust_demangling = DMGL_RUST + } current_demangling_style; + + /* Define string names for the various demangling styles. */ +@@ -104,6 +106,7 @@ extern enum demangling_styles + #define JAVA_DEMANGLING_STYLE_STRING "java" + #define GNAT_DEMANGLING_STYLE_STRING "gnat" + #define DLANG_DEMANGLING_STYLE_STRING "dlang" ++#define RUST_DEMANGLING_STYLE_STRING "rust" + + /* Some macros to test what demangling style is active. */ + +@@ -118,6 +121,7 @@ extern enum demangling_styles + #define JAVA_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_JAVA) + #define GNAT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNAT) + #define DLANG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_DLANG) ++#define RUST_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_RUST) + + /* Provide information about the available demangle styles. This code is + pulled from gdb into libiberty because it is useful to binutils also. */ +@@ -175,6 +179,27 @@ ada_demangle (const char *mangled, int o + extern char * + dlang_demangle (const char *mangled, int options); + ++/* Returns non-zero iff MANGLED is a rust mangled symbol. MANGLED must ++ already have been demangled through cplus_demangle_v3. If this function ++ returns non-zero then MANGLED can be demangled (in-place) using ++ RUST_DEMANGLE_SYM. */ ++extern int ++rust_is_mangled (const char *mangled); ++ ++/* Demangles SYM (in-place) if RUST_IS_MANGLED returned non-zero for SYM. ++ If RUST_IS_MANGLED returned zero for SYM then RUST_DEMANGLE_SYM might ++ replace characters that cannot be demangled with '?' and might truncate ++ SYM. After calling RUST_DEMANGLE_SYM SYM might be shorter, but never ++ larger. */ ++extern void ++rust_demangle_sym (char *sym); ++ ++/* Demangles MANGLED if it was GNU_V3 and then RUST mangled, otherwise ++ returns NULL. Uses CPLUS_DEMANGLE_V3, RUST_IS_MANGLED and ++ RUST_DEMANGLE_SYM. Returns a new string that is owned by the caller. */ ++extern char * ++rust_demangle (const char *mangled, int options); ++ + enum gnu_v3_ctor_kinds { + gnu_v3_complete_object_ctor = 1, + gnu_v3_base_object_ctor, +@@ -449,7 +474,9 @@ enum demangle_component_type + /* A transaction-safe function type. */ + DEMANGLE_COMPONENT_TRANSACTION_SAFE, + /* A cloned function. */ +- DEMANGLE_COMPONENT_CLONE ++ DEMANGLE_COMPONENT_CLONE, ++ DEMANGLE_COMPONENT_NOEXCEPT, ++ DEMANGLE_COMPONENT_THROW_SPEC + }; + + /* Types which are only used internally. */ |