Bug 70909 - Libiberty Demangler segfaults (4)
Summary: Libiberty Demangler segfaults (4)
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: demangler (show other bugs)
Version: unknown
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: 67264
  Show dependency treegraph
 
Reported: 2016-05-02 14:16 UTC by Marcel Böhme
Modified: 2017-04-21 09:02 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-11-19 00:00:00


Attachments
compile with gcc 6.2 -std=c++14 (571 bytes, text/x-csrc)
2016-11-21 18:11 UTC, Matt Godbolt
Details
Add is_cyclic check to d_lookup_template_argument (660 bytes, patch)
2016-12-01 14:26 UTC, Mark Wielaard
Details | Diff
d_printing mark/walk/unmark protection (903 bytes, patch)
2016-12-02 16:01 UTC, Mark Wielaard
Details | Diff
Check output with d_printing.patch (1.36 KB, text/plain)
2016-12-02 16:03 UTC, Mark Wielaard
Details
d_print_comp with 1 level of recursion protection (2.52 KB, patch)
2016-12-02 17:42 UTC, Mark Wielaard
Details | Diff
infinite d_print_comp printing protection (2.95 KB, patch)
2016-12-12 23:22 UTC, Mark Wielaard
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Marcel Böhme 2016-05-02 14:16:33 UTC
A stack overflow in the libiberty demangler library causes its host applications to crash. The stack contains return addresses that are not mapped in the inferior's process address space and/or the stack pointer is pointing to a location outside the default stack region. These conditions likely indicate stack corruption, which is generally considered exploitable.

How to reproduce:
$ valgind c++filt _Z1MA_aMMMMA_MMA_MMMMMMMMSt1MS_o11T0000000000t2M0oooozoooo
==80066== Stack overflow in thread 1: can't grow stack to 0xffe801ff8
==80066== 
==80066== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==80066==  Access not within mapped region at address 0xFFE801FF8
==80066==    at 0x78CAA4: d_print_comp_inner (cp-demangle.c:4332)

This specific stack overflow has not been reported but with a bit of searching it seems to be linked to the open bugs PR61460, PR68700, PR67738, PR68383, PR70517, PR61805, PR62279, and the meta bug PR67264. The prepared patch addresses all of these.

Analysis: The method d_print_comp in cp-demangle.c recursively constructs the d_print_info dpi from the demangle_component dc. The method d_print_comp_inner traverses dc as a graph. Now, dc can be a graph with cycles leading to infinite recursion in several distinct cases. 

This vulnerability was found with a more efficient version of AFL.
Comment 1 Stephan Bergmann 2016-08-23 13:44:55 UTC
(In reply to Marcel Böhme from comment #0)
> This specific stack overflow has not been reported but with a bit of
> searching it seems to be linked to the open bugs PR61460, PR68700, PR67738,
> PR68383, PR70517, PR61805, PR62279, and the meta bug PR67264. The prepared
> patch addresses all of these.

Is that patch available anywhere?
Comment 2 Marcel Böhme 2016-08-23 14:09:00 UTC
Here: https://gcc.gnu.org/ml/gcc-patches/2016-05/msg00105.html
Pending review.
Comment 3 Pedro Alves 2016-10-19 15:18:51 UTC
These crashes are still plaguing GDB users, unfortunately.

Any chance the patches make it to trunk?
Comment 4 Matt Godbolt 2016-10-21 13:12:47 UTC
We just hit this too with code using https://github.com/rollbear/trompeloeil/. The symbol '_ZSt4moveIRZN11trompeloeil13call_modifierINS0_12call_matcherIFiiESt5tupleIJNS0_17predicate_matcherIZNS0_11any_matcherIiEEDaPKcEUlOT_E_ZNS6_IiEES7_S9_EUlRSoE_NS0_13typed_matcherIiEEJEEEEEEEN6mock_c36trompeloeil_tag_type_trompeloeil_135ENS0_12matcher_infoIS3_EEE12handle_throwIZN12_GLOBAL__N_131____C_A_T_C_H____T_E_S_T____6454testEvE4$_42EENS1_ISJ_SL_NS0_14throw_injectorISN_EEEESB_EUlRSA_E_EONSt16remove_referenceISA_E4typeESB_' causes both c++filt and gdb to crash.
Comment 5 Markus Trippelsdorf 2016-10-21 13:16:56 UTC
(In reply to Matt Godbolt from comment #4)
> We just hit this too with code using
> https://github.com/rollbear/trompeloeil/. The symbol
> '_ZSt4moveIRZN11trompeloeil13call_modifierINS0_12call_matcherIFiiESt5tupleIJN
> S0_17predicate_matcherIZNS0_11any_matcherIiEEDaPKcEUlOT_E_ZNS6_IiEES7_S9_EUlR
> SoE_NS0_13typed_matcherIiEEJEEEEEEEN6mock_c36trompeloeil_tag_type_trompeloeil
> _135ENS0_12matcher_infoIS3_EEE12handle_throwIZN12_GLOBAL__N_131____C_A_T_C_H_
> ___T_E_S_T____6454testEvE4$_42EENS1_ISJ_SL_NS0_14throw_injectorISN_EEEESB_EUl
> RSA_E_EONSt16remove_referenceISA_E4typeESB_' causes both c++filt and gdb to
> crash.

This is already fixed on trunk.
Comment 6 Robert Schiele 2016-11-08 07:38:20 UTC
*** Bug 67738 has been marked as a duplicate of this bug. ***
Comment 7 Mark Wielaard 2016-11-19 13:55:21 UTC
(In reply to Markus Trippelsdorf from comment #5)
> (In reply to Matt Godbolt from comment #4)
> > We just hit this too with code using
> > https://github.com/rollbear/trompeloeil/. The symbol
> > '_ZSt4moveIRZN11trompeloeil13call_modifierINS0_12call_matcherIFiiESt5tupleIJN
> > S0_17predicate_matcherIZNS0_11any_matcherIiEEDaPKcEUlOT_E_ZNS6_IiEES7_S9_EUlR
> > SoE_NS0_13typed_matcherIiEEJEEEEEEEN6mock_c36trompeloeil_tag_type_trompeloeil
> > _135ENS0_12matcher_infoIS3_EEE12handle_throwIZN12_GLOBAL__N_131____C_A_T_C_H_
> > ___T_E_S_T____6454testEvE4$_42EENS1_ISJ_SL_NS0_14throw_injectorISN_EEEESB_EUl
> > RSA_E_EONSt16remove_referenceISA_E4typeESB_' causes both c++filt and gdb to
> > crash.
> 
> This is already fixed on trunk.

Are you sure? The symbol still seems to crash for me and it seems the proposed patch has not gotten in yet.
Comment 8 Markus Trippelsdorf 2016-11-19 14:03:37 UTC
(In reply to Mark Wielaard from comment #7)
> (In reply to Markus Trippelsdorf from comment #5)
> > (In reply to Matt Godbolt from comment #4)
> > > We just hit this too with code using
> > > https://github.com/rollbear/trompeloeil/. The symbol
> > > '_ZSt4moveIRZN11trompeloeil13call_modifierINS0_12call_matcherIFiiESt5tupleIJN
> > > S0_17predicate_matcherIZNS0_11any_matcherIiEEDaPKcEUlOT_E_ZNS6_IiEES7_S9_EUlR
> > > SoE_NS0_13typed_matcherIiEEJEEEEEEEN6mock_c36trompeloeil_tag_type_trompeloeil
> > > _135ENS0_12matcher_infoIS3_EEE12handle_throwIZN12_GLOBAL__N_131____C_A_T_C_H_
> > > ___T_E_S_T____6454testEvE4$_42EENS1_ISJ_SL_NS0_14throw_injectorISN_EEEESB_EUl
> > > RSA_E_EONSt16remove_referenceISA_E4typeESB_' causes both c++filt and gdb to
> > > crash.
> > 
> > This is already fixed on trunk.
> 
> Are you sure? The symbol still seems to crash for me and it seems the
> proposed patch has not gotten in yet.

Sorry, you're right. My shell messed up the symbol. When I quote it
c++filt still crashes.

This is what it should look like:

std::remove_reference<int&&>::type&& std::move<trompeloeil::call_modifier<mock_c, trompeloeil::matcher_info, trompeloeil::throw_injector<trompeloeil::call_modifier<trompeloeil::call_matcher<int (int), std::tuple<trompeloeil::predicate_matcher<auto trompeloeil::any_matcher<int>(char const*)::'lambda'(int&&), char const trompeloeil::any_matcher<int>(int)::'lambda'(std::ostream&), trompeloeil::typed_matcher<int> > > >, mock_c::trompeloeil_tag_type_trompeloeil_135, trompeloeil::matcher_info<int (int)> > > > trompeloeil::call_modifier<trompeloeil::call_matcher<int (int), std::tuple<trompeloeil::predicate_matcher<auto trompeloeil::any_matcher<int>(char const*)::'lambda'(int&&), char const trompeloeil::any_matcher<int>(int)::'lambda'(std::ostream&), trompeloeil::typed_matcher<int> > > >, mock_c::trompeloeil_tag_type_trompeloeil_135, trompeloeil::matcher_info<int (int)> >::handle_throw<(anonymous namespace)::____C_A_T_C_H____T_E_S_T____645::test()::$_42>(auto trompeloeil::any_matcher<int>(char const*)::'lambda'(int&&))::'lambda'(int&&&)&>(auto trompeloeil::any_matcher<int>(char const*)::'lambda'(int&&))
Comment 9 Mark Wielaard 2016-11-19 16:46:53 UTC
(In reply to Markus Trippelsdorf from comment #8)
> This is what it should look like: [...]

How did you demangle that input string?
With the proposed patch the mangled string is rejected by the libiberty demangler.

I assume since you were able to demangle it is a valid input string, but that the demangler creates a cyclic graph for it that then blows up the stack when trying to print out.


A smaller, valid, reproducer would be nice to have. Clearly some of the inputs that crash the demangler because it creates a cycle in the parse graph are bogus and should be rejected.

It isn't immediately clear to me whether the bug is that a cyclic graph is created for this input string, or that the bug is that such a cycle is printed out naively.
Comment 10 Markus Trippelsdorf 2016-11-19 16:56:33 UTC
(In reply to Mark Wielaard from comment #9)
> (In reply to Markus Trippelsdorf from comment #8)
> > This is what it should look like: [...]
> 
> How did you demangle that input string?
> With the proposed patch the mangled string is rejected by the libiberty
> demangler.
> 
> I assume since you were able to demangle it is a valid input string, but
> that the demangler creates a cyclic graph for it that then blows up the
> stack when trying to print out.

There a three demanglers that I know of. 
 libiberty
 Ian's demangler (written in Go) https://github.com/ianlancetaylor/demangle
 and LLVM's libc++abi demangler http://libcxxabi.llvm.org/

The symbol was demangled with libcxxabi's demangler.
The other two demanglers reject it.
Comment 11 Mark Wielaard 2016-11-19 18:43:26 UTC
(In reply to Markus Trippelsdorf from comment #10)
> The symbol was demangled with libcxxabi's demangler.
> The other two demanglers reject it.

Thanks. Do you know which demangler is correct for this input string?
The question is whether this symbol was incorrectly generated. If so then rejecting it is it the right thing to do. If it is correct then there is still the question whether the produced output is correct. Which is slightly hard given how big this input/output pair is.

Does anybody have a smaller (valid) reproducer?
Comment 12 Markus Trippelsdorf 2016-11-19 19:59:50 UTC
(In reply to Mark Wielaard from comment #11)
> (In reply to Markus Trippelsdorf from comment #10)
> > The symbol was demangled with libcxxabi's demangler.
> > The other two demanglers reject it.
> 
> Thanks. Do you know which demangler is correct for this input string?
> The question is whether this symbol was incorrectly generated. If so then
> rejecting it is it the right thing to do. If it is correct then there is
> still the question whether the produced output is correct. Which is slightly
> hard given how big this input/output pair is.

I'm not sure. The libc++abi demangler is rather permissive, so anything
it accepts doesn't necessarily have to be correct.

Perhaps Matt could attach a preprocessed testcase that produces the symbol?
Comment 13 Matt Godbolt 2016-11-21 14:13:09 UTC
We will try and get a small repro case. It comes from open source software: it's from the compiling_tests.cpp program in trompeloeil (https://github.com/rollbear/trompeloeil/blob/master/compiling_tests.cpp. The trompeloeil author is going to try and make a cut-down case.
Comment 14 Matt Godbolt 2016-11-21 18:11:06 UTC
Created attachment 40101 [details]
compile with gcc 6.2 -std=c++14

This reproduces the issue. Compile with g++ 6.2 and -std=c++14 to create a file which contains the symbol:

_ZSt7forwardIR17predicate_matcherIZ11any_matcherIiEDavEUlOT_E_13typed_matcherIiEEES3_RNSt16remove_referenceIS2_E4typeE

This symbol crashes both c++filt (2.26.20160125) and gdb (7.10) in the same way as this bug describes (d_print_comp infinite recursion).
Comment 15 Markus Trippelsdorf 2016-11-21 18:23:18 UTC
Thanks for the testcase.
Marcel's patch fixes the segfault, but doesn't demangle the symbol.

markus@x4 libiberty % ./a.out _ZSt7forwardIR17predicate_matcherIZ11any_matcherIiEDavEUlOT_E_13typed_matcherIiEEES3_RNSt16remove_referenceIS2_E4typeE
typed name
  template
    qualified name
      name 'std'
      name 'forward'
    template argument list
      reference
        template
          name 'predicate_matcher'
          template argument list
            local name
              typed name
                template
                  name 'any_matcher'
                  template argument list
                    builtin type int
                function type
                  name 'auto'
                  argument list
              lambda 0
                argument list
                  rvalue reference
                    template parameter 0
            template argument list
              template
                name 'typed_matcher'
                template argument list
                  builtin type int
  function type
    rvalue reference
      template parameter 0
    argument list
      reference
        qualified name
          template
            qualified name
              standard substitution std
              name 'remove_reference'
            template argument list
              template parameter 0
          name 'type'
Failed: _ZSt7forwardIR17predicate_matcherIZ11any_matcherIiEDavEUlOT_E_13typed_matcherIiEEES3_RNSt16remove_referenceIS2_E4typeE

libc++abi demangler gives:
int&& std::forward<predicate_matcher<auto any_matcher<int>()::'lambda'(int&&), typed_matcher<int> >&>(std::remove_reference<int>::type&)
Comment 16 Matt Godbolt 2016-11-22 14:14:38 UTC
Just to be clear; I've been told GCC 6.2 is not required to compile the code I linked; the earliest compiler it has been repro'd with is 4.9 (though we haven't tested further back). It's also the mangled name created by the current trunk of GCC 7.
Comment 17 Markus Trippelsdorf 2016-12-01 07:54:18 UTC
Nathan's patch fixes this issue:
https://patchwork.ozlabs.org/patch/701137/
It is currently being reviewed.
Comment 18 Marcel Böhme 2016-12-01 09:16:55 UTC
(In reply to Markus Trippelsdorf from comment #17)
> Nathan's patch fixes this issue:
> https://patchwork.ozlabs.org/patch/701137/
> It is currently being reviewed.

It doesn't seem to fix the original issue for me.
$ binutils-gdb/build/binutils/cxxfilt _Z1MA_aMMMMA_MMA_MMMMMMMMSt1MS_o11T0000000000t2M0oooozoooo
Segmentation fault

With Valgrind complaining:
==108073== Memcheck, a memory error detector
==108073== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==108073== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==108073== Command: binutils-gdb/build/binutils/cxxfilt _Z1MA_aMMMMA_MMA_MMMMMMMMSt1MS_o11T0000000000t2M0oooozoooo
==108073== 
==108073== Stack overflow in thread 1: can't grow stack to 0xffe801fe8
==108073== 
==108073== Process terminating with default action of signal 11 (SIGSEGV)
==108073==  Access not within mapped region at address 0xFFE801FE8
==108073==    at 0x7D9704: d_print_comp_inner (cp-demangle.c:4587)
Comment 19 Nathan Sidwell 2016-12-01 12:22:24 UTC
The original issue doesn't appear to be a lambda mangling, so I don't think related to 78252.  I do see lambda manglings in some of the other symbols mentioned in this bug, and I can well believe those are the same as 78252.
Comment 20 Mark Wielaard 2016-12-01 14:26:50 UTC
Created attachment 40213 [details]
Add is_cyclic check to d_lookup_template_argument

The patch that Marcel originally proposed tried to catch any recursive printing and if so stop (but not fail) the demangling.

The reviews seemed to suggest that people found this a bit too costly and that the check should be more specific and that it should produce an error.
https://gcc.gnu.org/ml/gcc-patches/2016-05/msg02093.html
https://gcc.gnu.org/ml/gcc-patches/2016-06/msg01985.html

So maybe we should extract the cyclic detection so it can be used in "debug mode" and inserted in the "right place".

The attached does that (minus adding a debug mode) and catches some of the crashes.
Comment 21 Nathan Sidwell 2016-12-01 14:53:29 UTC
Why doesn't a mark/walk/unmark idiom when walking a potentially circular data structure work here?  I.e. add a mutable counter to demangle_component.  Inc/dec at start/end of d_print_comp? IIUC if it gets to >1 there's a problem.
Comment 22 Mark Wielaard 2016-12-02 16:01:37 UTC
Created attachment 40230 [details]
d_printing mark/walk/unmark protection

(In reply to Nathan Sidwell from comment #21)
> Why doesn't a mark/walk/unmark idiom when walking a potentially circular
> data structure work here?  I.e. add a mutable counter to demangle_component.
> Inc/dec at start/end of d_print_comp? IIUC if it gets to >1 there's a
> problem.

That is a good idea. However it seems things aren't as simple as that.
The attached patch implements it, but that produces various testsuite failures:
./test-demangle: 960 tests, 7 failures

It might of course be that I messed up the check or that any of these failures really are bad.
Comment 23 Mark Wielaard 2016-12-02 16:03:20 UTC
Created attachment 40231 [details]
Check output with d_printing.patch
Comment 24 Markus Trippelsdorf 2016-12-02 17:16:53 UTC
(In reply to Mark Wielaard from comment #22)
> Created attachment 40230 [details]
> d_printing mark/walk/unmark protection
> 
> (In reply to Nathan Sidwell from comment #21)
> > Why doesn't a mark/walk/unmark idiom when walking a potentially circular
> > data structure work here?  I.e. add a mutable counter to demangle_component.
> > Inc/dec at start/end of d_print_comp? IIUC if it gets to >1 there's a
> > problem.
> 
> That is a good idea. However it seems things aren't as simple as that.
> The attached patch implements it, but that produces various testsuite
> failures:
> ./test-demangle: 960 tests, 7 failures
> 
> It might of course be that I messed up the check or that any of these
> failures really are bad.

You need to allow one more level of recursion. The following variant works fine: 

+  /* We need to cheat for the endless recursive printing protection.  */
+  struct demangle_component *dc1 = (struct demangle_component *) dc;
+  if (dc1 == NULL || dc1->d_printing > 1)
+    {
+      d_print_error (dpi);
+      return;
+    }
+  else
+    dc1->d_printing += 1;
Comment 25 Mark Wielaard 2016-12-02 17:38:17 UTC
(In reply to Markus Trippelsdorf from comment #24)
> (In reply to Mark Wielaard from comment #22)
> > Created attachment 40230 [details]
> > d_printing mark/walk/unmark protection
> > 
> > (In reply to Nathan Sidwell from comment #21)
> > > Why doesn't a mark/walk/unmark idiom when walking a potentially circular
> > > data structure work here?  I.e. add a mutable counter to demangle_component.
> > > Inc/dec at start/end of d_print_comp? IIUC if it gets to >1 there's a
> > > problem.
> > 
> > That is a good idea. However it seems things aren't as simple as that.
> > The attached patch implements it, but that produces various testsuite
> > failures:
> > ./test-demangle: 960 tests, 7 failures
> > 
> > It might of course be that I messed up the check or that any of these
> > failures really are bad.
> 
> You need to allow one more level of recursion. The following variant works
> fine: 

Indeed it does!
Why do we need the extra recursion level?

This prevents crashes for various issues collected in this and other PRs.
The only question is if those mangled symbols are all really bad. There are a couple that don't demangle, but where the user seems to expect they would. Of course they certainly don't expect to crash the demangler, so it is an improvement, but some extra investigation seems necessary.
Comment 26 Mark Wielaard 2016-12-02 17:42:42 UTC
Created attachment 40233 [details]
d_print_comp with 1 level of recursion protection

This is the variant that allows 1 level of recursion (with an xxx ??? to why 1 level). Plus various symbols added to demangle-expected from PRs that used to crash the demangler because of endless recursion.

The question now is whether this really is a good fix or if some of these symbols really should demangle to something meaningful.
Comment 27 Nathan Sidwell 2016-12-02 17:51:32 UTC
I think the symbols containing 'Ul' should demangle -- they're lambdas and I'd expect my patch to fix those.  Some of the others certainly look suspicious.  Did they come out of the compiler, or are they the result of fuzzing?

IMHO it'd be better to change d_print_comp to take a pointer to non-constant demangle_component, rather than use casts in the function. (I realize current patch may just be a proof of concept.)  It looks a good approach to me.
Comment 28 Markus Trippelsdorf 2016-12-02 17:58:18 UTC
(In reply to Mark Wielaard from comment #26)
> Created attachment 40233 [details]
> d_print_comp with 1 level of recursion protection
> 
> This is the variant that allows 1 level of recursion (with an xxx ??? to why
> 1 level). Plus various symbols added to demangle-expected from PRs that used
> to crash the demangler because of endless recursion.
> 
> The question now is whether this really is a good fix or if some of these
> symbols really should demangle to something meaningful.

It is always better not to crash. 

Please also note that Nathan's lambda demangling patch needs adjustments,
because with level 1 of recursion it prints everything twice.
Comment 29 Nathan Sidwell 2016-12-02 18:02:38 UTC
On 12/02/2016 12:58 PM, trippels at gcc dot gnu.org wrote:

> Please also note that Nathan's lambda demangling patch needs adjustments,
> because with level 1 of recursion it prints everything twice.

sorry, please clarify.  With what symbol(s)?

nathan
Comment 30 Markus Trippelsdorf 2016-12-02 18:06:25 UTC
(In reply to Nathan Sidwell from comment #29)
> On 12/02/2016 12:58 PM, trippels at gcc dot gnu.org wrote:
> 
> > Please also note that Nathan's lambda demangling patch needs adjustments,
> > because with level 1 of recursion it prints everything twice.
> 
> sorry, please clarify.  With what symbol(s)?

Sorry please ignore my statement, it has nothing to do with Mark's patch.

I mean, e.g. (c++filt__ is from libcxxabi, c++filt is libiberty with Nathan's patch)

markus@x4 libiberty % c++filt__ _ZSt7forwardIR17predicate_matcherIZ11any_matcherIiEDavEUlOT_E_13typed_matcherIiEEES3_RNSt16remove_referenceIS2_E4typeE
int&& std::forward<predicate_matcher<auto any_matcher<int>()::'lambda'(int&&), typed_matcher<int> >&>(std::remove_reference<int>::type&)
markus@x4 libiberty % c++filt _ZSt7forwardIR17predicate_matcherIZ11any_matcherIiEDavEUlOT_E_13typed_matcherIiEEES3_RNSt16remove_referenceIS2_E4typeE
predicate_matcher<auto any_matcher<int>()::{lambda(auto&&)#1}, typed_matcher<int> >& std::forward<predicate_matcher<auto any_matcher<int>()::{lambda(auto&&)#1}, typed_matcher<int> >&>(std::remove_reference<predicate_matcher<auto any_matcher<int>()::{lambda(auto&&)#1}, typed_matcher<int> >&>::type&)
markus@x4 libiberty % c++filt__ _ZN4eggs8variants6detail7forwardIOZN5ossia15vec_merger_implILi2EEclINS0_7variantIJNS3_12strong_valueINS3_11speed_ratioISt5ratioILl1ELl1EEEEEENS8_INS9_ISA_ILl16093440ELl36000000EEEEEENS8_INS9_ISA_ILl1000ELl3600EEEEEENS8_INS9_ISA_ILl1852ELl3600EEEEEENS8_INS9_ISA_ILl3048ELl10000EEEEEENS8_INS9_ISA_ILl3048ELl36000000EEEEEEEEEEENS7_IJNS3_5valueENS7_IJNS8_INS3_14distance_ratioISB_EEEENS8_INSV_ISA_ILl1000ELl1EEEEEENS8_INSV_ISA_ILl1ELl10EEEEEENS8_INSV_ISA_ILl1ELl100EEEEEENS8_INSV_ISA_ILl1ELl1000EEEEEENS8_INSV_ISA_ILl1ELl1000000EEEEEENS8_INSV_ISA_ILl1ELl1000000000EEEEEENS8_INSV_ISA_ILl1ELl1000000000000EEEEEENS8_INSV_ISA_ILl254ELl10000EEEEEENS8_INSV_ISN_EEEENS8_INSV_ISA_ILl16093440ELl10000EEEEEEEEENS7_IJNS8_INS3_14cartesian_3d_uEEENS8_INS3_14cartesian_2d_uEEENS8_INS3_11spherical_uEEENS8_INS3_7polar_uEEENS8_INS3_8opengl_uEEENS8_INS3_13cylindrical_uEEEEEEST_NS7_IJNS8_INS3_12quaternion_uEEENS8_INS3_7euler_uEEENS8_INS3_6axis_uEEEEEENS7_IJNS8_INS3_8degree_uEEENS8_INS3_8radian_uEEEEEENS7_IJNS8_INS3_6argb_uEEENS8_INS3_6rgba_uEEENS8_INS3_5rgb_uEEENS8_INS3_5bgr_uEEENS8_INS3_7argb8_uEEENS8_INS3_5hsv_uEEENS8_INS3_6cmy8_uEEENS8_INS3_5xyz_uEEEEEENS7_IJNS8_INS3_8linear_uEEENS8_INS3_10midigain_uEEENS8_INS3_9decibel_uEEENS8_INS3_13decibel_raw_uEEEEEEEEERKT_EUlRS38_E_EEOS38_RNSt16remove_referenceIS38_E4typeE
eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > >&& eggs::variants::detail::forward<eggs::variants::variant<ossia::value, eggs::variants::variant<ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1000l, 1l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 10l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 100l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000000000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000000000000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<254l, 10000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<16093440l, 10000l> > > >, eggs::variants::variant<ossia::strong_value<ossia::cartesian_3d_u>, ossia::strong_value<ossia::cartesian_2d_u>, ossia::strong_value<ossia::spherical_u>, ossia::strong_value<ossia::polar_u>, ossia::strong_value<ossia::opengl_u>, ossia::strong_value<ossia::cylindrical_u> >, eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > >, eggs::variants::variant<ossia::strong_value<ossia::quaternion_u>, ossia::strong_value<ossia::euler_u>, ossia::strong_value<ossia::axis_u> >, eggs::variants::variant<ossia::strong_value<ossia::degree_u>, ossia::strong_value<ossia::radian_u> >, eggs::variants::variant<ossia::strong_value<ossia::argb_u>, ossia::strong_value<ossia::rgba_u>, ossia::strong_value<ossia::rgb_u>, ossia::strong_value<ossia::bgr_u>, ossia::strong_value<ossia::argb8_u>, ossia::strong_value<ossia::hsv_u>, ossia::strong_value<ossia::cmy8_u>, ossia::strong_value<ossia::xyz_u> >, eggs::variants::variant<ossia::strong_value<ossia::linear_u>, ossia::strong_value<ossia::midigain_u>, ossia::strong_value<ossia::decibel_u>, ossia::strong_value<ossia::decibel_raw_u> > > ossia::vec_merger_impl<2>::operator()<eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > > >(eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > > const&)::'lambda'(eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > >&)&&>(std::remove_reference<eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > > >::type&)
markus@x4 libiberty % c++filt _ZN4eggs8variants6detail7forwardIOZN5ossia15vec_merger_implILi2EEclINS0_7variantIJNS3_12strong_valueINS3_11speed_ratioISt5ratioILl1ELl1EEEEEENS8_INS9_ISA_ILl16093440ELl36000000EEEEEENS8_INS9_ISA_ILl1000ELl3600EEEEEENS8_INS9_ISA_ILl1852ELl3600EEEEEENS8_INS9_ISA_ILl3048ELl10000EEEEEENS8_INS9_ISA_ILl3048ELl36000000EEEEEEEEEEENS7_IJNS3_5valueENS7_IJNS8_INS3_14distance_ratioISB_EEEENS8_INSV_ISA_ILl1000ELl1EEEEEENS8_INSV_ISA_ILl1ELl10EEEEEENS8_INSV_ISA_ILl1ELl100EEEEEENS8_INSV_ISA_ILl1ELl1000EEEEEENS8_INSV_ISA_ILl1ELl1000000EEEEEENS8_INSV_ISA_ILl1ELl1000000000EEEEEENS8_INSV_ISA_ILl1ELl1000000000000EEEEEENS8_INSV_ISA_ILl254ELl10000EEEEEENS8_INSV_ISN_EEEENS8_INSV_ISA_ILl16093440ELl10000EEEEEEEEENS7_IJNS8_INS3_14cartesian_3d_uEEENS8_INS3_14cartesian_2d_uEEENS8_INS3_11spherical_uEEENS8_INS3_7polar_uEEENS8_INS3_8opengl_uEEENS8_INS3_13cylindrical_uEEEEEEST_NS7_IJNS8_INS3_12quaternion_uEEENS8_INS3_7euler_uEEENS8_INS3_6axis_uEEEEEENS7_IJNS8_INS3_8degree_uEEENS8_INS3_8radian_uEEEEEENS7_IJNS8_INS3_6argb_uEEENS8_INS3_6rgba_uEEENS8_INS3_5rgb_uEEENS8_INS3_5bgr_uEEENS8_INS3_7argb8_uEEENS8_INS3_5hsv_uEEENS8_INS3_6cmy8_uEEENS8_INS3_5xyz_uEEEEEENS7_IJNS8_INS3_8linear_uEEENS8_INS3_10midigain_uEEENS8_INS3_9decibel_uEEENS8_INS3_13decibel_raw_uEEEEEEEEERKT_EUlRS38_E_EEOS38_RNSt16remove_referenceIS38_E4typeE
eggs::variants::variant<ossia::value, eggs::variants::variant<ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1000l, 1l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 10l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 100l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000000000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000000000000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<254l, 10000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<16093440l, 10000l> > > >, eggs::variants::variant<ossia::strong_value<ossia::cartesian_3d_u>, ossia::strong_value<ossia::cartesian_2d_u>, ossia::strong_value<ossia::spherical_u>, ossia::strong_value<ossia::polar_u>, ossia::strong_value<ossia::opengl_u>, ossia::strong_value<ossia::cylindrical_u> >, eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > >, eggs::variants::variant<ossia::strong_value<ossia::quaternion_u>, ossia::strong_value<ossia::euler_u>, ossia::strong_value<ossia::axis_u> >, eggs::variants::variant<ossia::strong_value<ossia::degree_u>, ossia::strong_value<ossia::radian_u> >, eggs::variants::variant<ossia::strong_value<ossia::argb_u>, ossia::strong_value<ossia::rgba_u>, ossia::strong_value<ossia::rgb_u>, ossia::strong_value<ossia::bgr_u>, ossia::strong_value<ossia::argb8_u>, ossia::strong_value<ossia::hsv_u>, ossia::strong_value<ossia::cmy8_u>, ossia::strong_value<ossia::xyz_u> >, eggs::variants::variant<ossia::strong_value<ossia::linear_u>, ossia::strong_value<ossia::midigain_u>, ossia::strong_value<ossia::decibel_u>, ossia::strong_value<ossia::decibel_raw_u> > > ossia::vec_merger_impl<2>::operator()<eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > > >(eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > > const&)::{lambda(auto&)#1}&& eggs::variants::detail::forward<eggs::variants::variant<ossia::value, eggs::variants::variant<ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1000l, 1l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 10l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 100l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000000000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000000000000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<254l, 10000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<16093440l, 10000l> > > >, eggs::variants::variant<ossia::strong_value<ossia::cartesian_3d_u>, ossia::strong_value<ossia::cartesian_2d_u>, ossia::strong_value<ossia::spherical_u>, ossia::strong_value<ossia::polar_u>, ossia::strong_value<ossia::opengl_u>, ossia::strong_value<ossia::cylindrical_u> >, eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > >, eggs::variants::variant<ossia::strong_value<ossia::quaternion_u>, ossia::strong_value<ossia::euler_u>, ossia::strong_value<ossia::axis_u> >, eggs::variants::variant<ossia::strong_value<ossia::degree_u>, ossia::strong_value<ossia::radian_u> >, eggs::variants::variant<ossia::strong_value<ossia::argb_u>, ossia::strong_value<ossia::rgba_u>, ossia::strong_value<ossia::rgb_u>, ossia::strong_value<ossia::bgr_u>, ossia::strong_value<ossia::argb8_u>, ossia::strong_value<ossia::hsv_u>, ossia::strong_value<ossia::cmy8_u>, ossia::strong_value<ossia::xyz_u> >, eggs::variants::variant<ossia::strong_value<ossia::linear_u>, ossia::strong_value<ossia::midigain_u>, ossia::strong_value<ossia::decibel_u>, ossia::strong_value<ossia::decibel_raw_u> > > ossia::vec_merger_impl<2>::operator()<eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > > >(eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > > const&)::{lambda(auto&)#1}&&>(std::remove_reference<eggs::variants::variant<ossia::value, eggs::variants::variant<ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1000l, 1l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 10l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 100l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000000000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<1l, 1000000000000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<254l, 10000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::distance_ratio<std::ratio<16093440l, 10000l> > > >, eggs::variants::variant<ossia::strong_value<ossia::cartesian_3d_u>, ossia::strong_value<ossia::cartesian_2d_u>, ossia::strong_value<ossia::spherical_u>, ossia::strong_value<ossia::polar_u>, ossia::strong_value<ossia::opengl_u>, ossia::strong_value<ossia::cylindrical_u> >, eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > >, eggs::variants::variant<ossia::strong_value<ossia::quaternion_u>, ossia::strong_value<ossia::euler_u>, ossia::strong_value<ossia::axis_u> >, eggs::variants::variant<ossia::strong_value<ossia::degree_u>, ossia::strong_value<ossia::radian_u> >, eggs::variants::variant<ossia::strong_value<ossia::argb_u>, ossia::strong_value<ossia::rgba_u>, ossia::strong_value<ossia::rgb_u>, ossia::strong_value<ossia::bgr_u>, ossia::strong_value<ossia::argb8_u>, ossia::strong_value<ossia::hsv_u>, ossia::strong_value<ossia::cmy8_u>, ossia::strong_value<ossia::xyz_u> >, eggs::variants::variant<ossia::strong_value<ossia::linear_u>, ossia::strong_value<ossia::midigain_u>, ossia::strong_value<ossia::decibel_u>, ossia::strong_value<ossia::decibel_raw_u> > > ossia::vec_merger_impl<2>::operator()<eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > > >(eggs::variants::variant<ossia::strong_value<ossia::speed_ratio<std::ratio<1l, 1l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<16093440l, 36000000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1000l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<1852l, 3600l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 10000l> > >, ossia::strong_value<ossia::speed_ratio<std::ratio<3048l, 36000000l> > > > const&)::{lambda(auto&)#1}&&>::type&)
Comment 31 Marcel Böhme 2016-12-02 21:45:18 UTC
Hi Mark,

Your patch looks good to me. One more thing: It seems that our patches evaluate these two mangled strings differently. Is it because of Nathan's patch? Can these strings be demangled properly at all?

> 
_ZNK6Common15ConvertingRangeIN5boost12range_detail17transformed_rangeIZN1a1b1cEbEUljE_KSt6vectorIjSaIjEEEEEcvT_IS7_INS4_1dESaISF_EEEEv

Common::ConvertingRange<boost::range_detail::transformed_range<a::b::c(bool)::{lambda(unsigned int)#1}, std::vector<unsigned int, std::allocator<unsigned int> > const> >::operator a::b::c(bool)::{lambda(unsigned int)#1}<a::d, std::allocator<Common::ConvertingRange<boost::range_detail::transformed_range<a::b::c(bool)::{lambda(unsigned int)#1}, std::vector<unsigned int, std::allocator<unsigned int> > const> >::operator > ><a::b::c(bool)::{lambda(unsigned int)#1}<a::d, std::allocator<Common::ConvertingRange<boost::range_detail::transformed_range<a::b::c(bool)::{lambda(unsigned int)#1}, std::vector<unsigned int, std::allocator<unsigned int> > const> >::operator Common::ConvertingRange<boost::range_detail::transformed_range<a::b::c(bool)::{lambda(unsigned int)#1}, std::vector<unsigned int, std::allocator<unsigned int> > const> >::operator > > >() const

> _ZNK6clover6detail11basic_rangeINS_13adaptor_rangeINS_9addressesEINS2_IRFRNS_5eventEP9_cl_eventEINS_14iterator_rangeIPKS7_EEEEEEEENS0_16iterator_adaptorIS3_INSG_IS9_ISC_EEEEEESI_EcvT_ISt6vectorIPS4_SaISN_EEvEEv

clover::detail::basic_range<clover::adaptor_range<clover::addresses, clover::adaptor_range<clover::event& (&)(_cl_event*), clover::iterator_range<_cl_event* const*> > >, clover::detail::iterator_adaptor<clover::addresses<clover::detail::iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event* const*> > > >, clover::detail::iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event* const*> > >::operator std::vector<clover::event*, std::allocator<clover::detail::basic_range<clover::adaptor_range<clover::addresses, clover::adaptor_range<clover::event& (&)(_cl_event*), clover::iterator_range<_cl_event* const*> > >, clover::detail::iterator_adaptor<clover::addresses<clover::detail::iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event* const*> > > >, clover::detail::iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event* const*> > >::operator > ><std::vector<clover::event*, std::allocator<clover::detail::basic_range<clover::adaptor_range<clover::addresses, clover::adaptor_range<clover::event& (&)(_cl_event*), clover::iterator_range<_cl_event* const*> > >, clover::detail::iterator_adaptor<clover::addresses<clover::detail::iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event* const*> > > >, clover::detail::iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event* const*> > >::operator clover::detail::basic_range<clover::adaptor_range<clover::addresses, clover::adaptor_range<clover::event& (&)(_cl_event*), clover::iterator_range<_cl_event* const*> > >, clover::detail::iterator_adaptor<clover::addresses<clover::detail::iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event* const*> > > >, clover::detail::iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event* const*> > >::operator > >, void>() const
Comment 32 Mark Wielaard 2016-12-03 11:59:56 UTC
(In reply to Nathan Sidwell from comment #27)
> I think the symbols containing 'Ul' should demangle -- they're lambdas and
> I'd expect my patch to fix those.

I applied your patch first and two more demangled. The one from PR68383:

_ZSt4moveIRZN11trompeloeil13call_modifierINS0_12call_matcherIFiiESt5tupleIJNS0_17predicate_matcherIZNS0_11any_matcherIiEEDaPKcEUlOT_E_ZNS6_IiEES7_S9_EUlRSoE_NS0_13typed_matcherIiEEJEEEEEEEN6mock_c36trompeloeil_tag_type_trompeloeil_135ENS0_12matcher_infoIS3_EEE12handle_throwIZN12_GLOBAL__N_131____C_A_T_C_H____T_E_S_T____6454testEvE4

And the one from PR70909:

_ZSt4moveIRZN11trompeloeil13call_modifierINS0_12call_matcherIFiiESt5tupleIJNS0_17predicate_matcherIZNS0_11any_matcherIiEEDaPKcEUlOT_E_ZNS6_IiEES7_S9_EUlRSoE_NS0_13typed_matcherIiEEJEEEEEEEN6mock_c36trompeloeil_tag_type_trompeloeil_135ENS0_12matcher_infoIS3_EEE12handle_throwIZN12_GLOBAL__N_131____C_A_T_C_H____T_E_S_T____6454testEvE4$_42EENS1_ISJ_SL_NS0_14throw_injectorISN_EEEESB_EUlRSA_E_EONSt16remove_referenceISA_E4typeESB_

> Some of the others certainly look
> suspicious.  Did they come out of the compiler, or are they the result of
> fuzzing?

Some came out of a compiler, some from some fuzzers. I just took all of them reported in the various bug reports. The ones that look like they didn't come from a fuzzer that still don't demangle with both patches applied are:

- PR70517
_ZSt4moveIRZN11tconcurrent6futureIvE4thenIZ5awaitIS2_EDaOT_EUlRKS6_E_EENS1_INSt5decayIDTclfp_defpTEEE4typeEEES7_EUlvE_EONSt16remove_referenceIS6_E4typeES7_
Different compilers produce a different mangled string. I suspect this is produced by a buggy compiler.

- PR67738
_ZNK6Common15ConvertingRangeIN5boost12range_detail17transformed_rangeIZN1a1b1cEbEUljE_KSt6vectorIjSaIjEEEEEcvT_IS7_INS4_1dESaISF_EEEEv
Bug claims this used to demangle to:
Common::ConvertingRange<boost::range_detail::transformed_range<a::b::c(bool)::{lambda(unsigned int)#1}, std::vector<unsigned int, std::allocator<unsigned int> > const> >::operator a::b::c(bool)::{lambda(unsigned int)#1}<a::d, std::allocator<a::d> ><a::b::c(bool)::{lambda(unsigned int)#1}<a::d, std::allocator<a::d> > >() cons

- PR68700
_ZN8futurizeI13frozen_schemaE5applyIRZN7seastar7shardedIN7service13storage_proxyEE9invoke_onIZZNS6_22init_messaging_serviceEvENKUljN5utils4UUIDEE8_clEjSA_EUlOT_E_6futureIJS0_EEEET0_jSD_EUlvE_JEEESG_SD_DpOT0_
This looks like it comes from a real compiler, dunno what it should demangle to.

- PR61460
_ZNK6clover6detail11basic_rangeINS_13adaptor_rangeINS_9addressesEINS2_IRFRNS_5eventEP9_cl_eventEINS_14iterator_rangeIPKS7_EEEEEEEENS0_16iterator_adaptorIS3_INSG_IS9_ISC_EEEEEESI_EcvT_ISt6vectorIPS4_SaISN_EEvEEv
The referenced GDB bug claims this comes from clover's libOpenCL in Mesa, but doesn't state which compiler.

I could leave those out of the test file and keep the bugs open (or reopen if they were closed as a duplicate of this bug) till we figure out which was what. The important point (for this bug) is that those symbols don't crash the demangler anymore.

> IMHO it'd be better to change d_print_comp to take a pointer to non-constant
> demangle_component, rather than use casts in the function.

I am not sure what the coding conventions should be in this case. I would see it as an implementation detail. Only for d_print_comp is this a (private) mutable field, for any other function, including the public ones the struct could be considered unmutable. At least for the (public) fields the caller cares about.
Comment 33 Markus Trippelsdorf 2016-12-03 12:10:11 UTC
(In reply to Mark Wielaard from comment #32)
> - PR70517
> _ZSt4moveIRZN11tconcurrent6futureIvE4thenIZ5awaitIS2_EDaOT_EUlRKS6_E_EENS1_IN
> St5decayIDTclfp_defpTEEE4typeEEES7_EUlvE_EONSt16remove_referenceIS6_E4typeES7
> _

This one demangles just fine with Nathan's patch.

> 
> - PR68700
> _ZN8futurizeI13frozen_schemaE5applyIRZN7seastar7shardedIN7service13storage_pr
> oxyEE9invoke_onIZZNS6_22init_messaging_serviceEvENKUljN5utils4UUIDEE8_clEjSA_
> EUlOT_E_6futureIJS0_EEEET0_jSD_EUlvE_JEEESG_SD_DpOT0_
> This looks like it comes from a real compiler, dunno what it should demangle
> to.

This one, too. 

> - PR61460
> _ZNK6clover6detail11basic_rangeINS_13adaptor_rangeINS_9addressesEINS2_IRFRNS_
> 5eventEP9_cl_eventEINS_14iterator_rangeIPKS7_EEEEEEEENS0_16iterator_adaptorIS
> 3_INSG_IS9_ISC_EEEEEESI_EcvT_ISt6vectorIPS4_SaISN_EEvEEv
> The referenced GDB bug claims this comes from clover's libOpenCL in Mesa,
> but doesn't state which compiler.

None of the three demanglers could handle this one.
Comment 34 Mark Wielaard 2016-12-03 12:22:42 UTC
(In reply to Mark Wielaard from comment #26)
> Created attachment 40233 [details]
> d_print_comp with 1 level of recursion protection
> 
> This is the variant that allows 1 level of recursion (with an xxx ??? to why
> 1 level).

I figured out why it should be d_printing > 1.
For function types we print the DEMANGLE_COMPONENT_FUNCTION_TYPE twice with different options depending on whether or not we want the return type printed or not.

If we apply Nathan's lambda patch then we need d_printing > 2.
With that we get two more symbols demangled.

- PR70517
_ZSt4moveIRZN11tconcurrent6futureIvE4thenIZ5awaitIS2_EDaOT_EUlRKS6_E_EENS1_INSt5decayIDTclfp_defpTEEE4typeEEES7_EUlvE_EONSt16remove_referenceIS6_E4typeES7_

- PR68700
_ZN8futurizeI13frozen_schemaE5applyIRZN7seastar7shardedIN7service13storage_proxyEE9invoke_onIZZNS6_22init_messaging_serviceEvENKUljN5utils4UUIDEE8_clEjSA_EUlOT_E_6futureIJS0_EEEET0_jSD_EUlvE_JEEESG_SD_DpOT0_

So that leaves us with only two unexplained symbols that don't demangle PR61460 and PR67738.

I haven't figured out yet why with the lambda patch applied we need to allow 2 levels of recursion.
Comment 35 Mark Wielaard 2016-12-03 12:31:50 UTC
(In reply to Marcel Böhme from comment #31)
> Hi Mark,
> 
> Your patch looks good to me. One more thing: It seems that our patches
> evaluate these two mangled strings differently. Is it because of Nathan's
> patch? Can these strings be demangled properly at all?
> 
> > 
> _ZNK6Common15ConvertingRangeIN5boost12range_detail17transformed_rangeIZN1a1b1
> cEbEUljE_KSt6vectorIjSaIjEEEEEcvT_IS7_INS4_1dESaISF_EEEEv
> 
> Common::ConvertingRange<boost::range_detail::transformed_range<a::b::c(bool):
> :{lambda(unsigned int)#1}, std::vector<unsigned int, std::allocator<unsigned
> int> > const> >::operator a::b::c(bool)::{lambda(unsigned int)#1}<a::d,
> std::allocator<Common::ConvertingRange<boost::range_detail::
> transformed_range<a::b::c(bool)::{lambda(unsigned int)#1},
> std::vector<unsigned int, std::allocator<unsigned int> > const> >::operator
> > ><a::b::c(bool)::{lambda(unsigned int)#1}<a::d,
> std::allocator<Common::ConvertingRange<boost::range_detail::
> transformed_range<a::b::c(bool)::{lambda(unsigned int)#1},
> std::vector<unsigned int, std::allocator<unsigned int> > const> >::operator
> Common::ConvertingRange<boost::range_detail::transformed_range<a::b::c(bool):
> :{lambda(unsigned int)#1}, std::vector<unsigned int, std::allocator<unsigned
> int> > const> >::operator > > >() const


This one is still a mystery. It comes from PR67738.

The other does demangle with Nathan's lambda patch if we allow two levels of recursion.
> > _ZNK6clover6detail11basic_rangeINS_13adaptor_rangeINS_9addressesEINS2_IRFRNS_5eventEP9_cl_eventEINS_14iterator_rangeIPKS7_EEEEEEEENS0_16iterator_adaptorIS3_INSG_IS9_ISC_EEEEEESI_EcvT_ISt6vectorIPS4_SaISN_EEvEEv
> 
> clover::detail::basic_range<clover::adaptor_range<clover::addresses,
> clover::adaptor_range<clover::event& (&)(_cl_event*),
> clover::iterator_range<_cl_event* const*> > >,
> clover::detail::iterator_adaptor<clover::addresses<clover::detail::
> iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event* const*> > > >,
> clover::detail::iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event*
> const*> > >::operator std::vector<clover::event*,
> std::allocator<clover::detail::basic_range<clover::adaptor_range<clover::
> addresses, clover::adaptor_range<clover::event& (&)(_cl_event*),
> clover::iterator_range<_cl_event* const*> > >,
> clover::detail::iterator_adaptor<clover::addresses<clover::detail::
> iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event* const*> > > >,
> clover::detail::iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event*
> const*> > >::operator > ><std::vector<clover::event*,
> std::allocator<clover::detail::basic_range<clover::adaptor_range<clover::
> addresses, clover::adaptor_range<clover::event& (&)(_cl_event*),
> clover::iterator_range<_cl_event* const*> > >,
> clover::detail::iterator_adaptor<clover::addresses<clover::detail::
> iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event* const*> > > >,
> clover::detail::iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event*
> const*> > >::operator
> clover::detail::basic_range<clover::adaptor_range<clover::addresses,
> clover::adaptor_range<clover::event& (&)(_cl_event*),
> clover::iterator_range<_cl_event* const*> > >,
> clover::detail::iterator_adaptor<clover::addresses<clover::detail::
> iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event* const*> > > >,
> clover::detail::iterator_adaptor<clover::event& (&)(_cl_event*)<_cl_event*
> const*> > >::operator > >, void>() const
Comment 36 Mark Wielaard 2016-12-03 12:34:48 UTC
(In reply to Markus Trippelsdorf from comment #33)
> (In reply to Mark Wielaard from comment #32)
> > - PR70517
> > _ZSt4moveIRZN11tconcurrent6futureIvE4thenIZ5awaitIS2_EDaOT_EUlRKS6_E_EENS1_IN
> > St5decayIDTclfp_defpTEEE4typeEEES7_EUlvE_EONSt16remove_referenceIS6_E4typeES7
> > _
> 
> This one demangles just fine with Nathan's patch.
> 
> > 
> > - PR68700
> > _ZN8futurizeI13frozen_schemaE5applyIRZN7seastar7shardedIN7service13storage_pr
> > oxyEE9invoke_onIZZNS6_22init_messaging_serviceEvENKUljN5utils4UUIDEE8_clEjSA_
> > EUlOT_E_6futureIJS0_EEEET0_jSD_EUlvE_JEEESG_SD_DpOT0_
> > This looks like it comes from a real compiler, dunno what it should demangle
> > to.
> 
> This one, too. 

You are right. Sorry our messages/investigations crossed. If I allow d_printing up to 2 levels they do (with Nathan's patch).

> > - PR61460
> > _ZNK6clover6detail11basic_rangeINS_13adaptor_rangeINS_9addressesEINS2_IRFRNS_
> > 5eventEP9_cl_eventEINS_14iterator_rangeIPKS7_EEEEEEEENS0_16iterator_adaptorIS
> > 3_INSG_IS9_ISC_EEEEEESI_EcvT_ISt6vectorIPS4_SaISN_EEvEEv
> > The referenced GDB bug claims this comes from clover's libOpenCL in Mesa,
> > but doesn't state which compiler.
> 
> None of the three demanglers could handle this one.

Does any of them handle the one from PR67738:
_ZNK6Common15ConvertingRangeIN5boost12range_detail17transformed_rangeIZN1a1b1cEbEUljE_KSt6vectorIjSaIjEEEEEcvT_IS7_INS4_1dESaISF_EEEEv
Comment 37 Markus Trippelsdorf 2016-12-03 12:42:16 UTC
(In reply to Mark Wielaard from comment #36)
> Does any of them handle the one from PR67738:
> _ZNK6Common15ConvertingRangeIN5boost12range_detail17transformed_rangeIZN1a1b1
> cEbEUljE_KSt6vectorIjSaIjEEEEEcvT_IS7_INS4_1dESaISF_EEEEv

Yes libcxxabi does.

(you could easily check this yourself:

 % git clone https://llvm.googlesource.com/libcxxabi
 % cd libcxxabi

(then apply this patch):

 diff --git a/src/cxa_demangle.cpp b/src/cxa_demangle.cpp
index c48883221290..1d188133b7f9 100644
--- a/src/cxa_demangle.cpp
+++ b/src/cxa_demangle.cpp
@@ -19,6 +19,7 @@
 #include <cstdlib>
 #include <cstring>
 #include <cctype>
+#include <iostream>

 #ifdef _MSC_VER
 // snprintf is implemented in VS 2015
@@ -5041,3 +5042,12 @@ __cxa_demangle(const char *mangled_name, char *buf, size_t *n, int *status) {
 }

 }  // __cxxabiv1
+
+int
+main(int argc, char** argv) {
+    for (int i = 1, status = 0; i < argc; ++i)
+    {
+        char* dm = __cxxabiv1::__cxa_demangle(argv[i], NULL, NULL, &status);
+        std::cout << (status ? argv[i] : dm) << "\n";
+    }
+}

 % cd src
 % g++ -O2 -I../include cxa_demangle.cpp -o c++filt__
)
Comment 38 Mark Wielaard 2016-12-04 23:15:34 UTC
For reference the symbols in comment #4 and the reduced case from comment #14 are fixed by the patch proposed for Bug 78252 - C++ demangler crashes with infinite recursion with lambda (auto).

The patch proposed for this bug is for generic infinite recursion protection for symbols like in the original description (or fuzzed ones like in bug #67264).
Comment 39 Markus Trippelsdorf 2016-12-12 14:32:55 UTC
Mark, could you please post your path to gcc-patches?
Then there might be a chance to get it into binutils before 2.28 gets released.
Comment 40 Mark Wielaard 2016-12-12 23:22:14 UTC
Created attachment 40316 [details]
infinite d_print_comp printing protection

(In reply to Markus Trippelsdorf from comment #39)
> Mark, could you please post your path to gcc-patches?
> Then there might be a chance to get it into binutils before 2.28 gets
> released.

I did rewrite the patch a little to remove the const arguments, add just the testcases it fixes and allow up to 2 levels of recursion. That is attached.

But I still haven't figured out why we need to allow 2 levels of recursion for some of the cases. See the XXX in the patch. I don't feel I can propose this unless we figure out why the level needs to be 2 (and not 3 or...)

If we figure that out we should add the explanation to the comment. Then we can propose it on gcc-patches.
Comment 41 Markus Trippelsdorf 2016-12-13 07:19:09 UTC
(In reply to Mark Wielaard from comment #40)
> Created attachment 40316 [details]
> infinite d_print_comp printing protection
> 
> (In reply to Markus Trippelsdorf from comment #39)
> > Mark, could you please post your path to gcc-patches?
> > Then there might be a chance to get it into binutils before 2.28 gets
> > released.
> 
> I did rewrite the patch a little to remove the const arguments, add just the
> testcases it fixes and allow up to 2 levels of recursion. That is attached.
> 
> But I still haven't figured out why we need to allow 2 levels of recursion
> for some of the cases. See the XXX in the patch. I don't feel I can propose
> this unless we figure out why the level needs to be 2 (and not 3 or...)
> 
> If we figure that out we should add the explanation to the comment. Then we
> can propose it on gcc-patches.

Well, then just use one level of recursion in the patch. And increase the level 
in a possible follow-up patch later on. This will fix most stack overflows. 
If we fail to demangle some weird symbols at first, so be it.
Comment 42 Mark Wielaard 2016-12-13 13:39:18 UTC
(In reply to Markus Trippelsdorf from comment #41)
> (In reply to Mark Wielaard from comment #40)
> > But I still haven't figured out why we need to allow 2 levels of recursion
> > for some of the cases. See the XXX in the patch. I don't feel I can propose
> > this unless we figure out why the level needs to be 2 (and not 3 or...)
> > 
> > If we figure that out we should add the explanation to the comment. Then we
> > can propose it on gcc-patches.
> 
> Well, then just use one level of recursion in the patch. And increase the
> level 
> in a possible follow-up patch later on. This will fix most stack overflows. 
> If we fail to demangle some weird symbols at first, so be it.

That would break demangling of symbols from e.g. bug 68700
_ZN8futurizeI13frozen_schemaE5applyIRZN7seastar7shardedIN7service13storage_proxyEE9invoke_onIZZNS6_22init_messaging_serviceEvENKUljN5utils4UUIDEE8_clEjSA_EUlOT_E_6futureIJS0_EEEET0_jSD_EUlvE_JEEESG_SD_DpOT0_
or bug #70517
_ZSt4moveIRZN11tconcurrent6futureIvE4thenIZ5awaitIS2_EDaOT_EUlRKS6_E_EENS1_INSt5decayIDTclfp_defpTEEE4typeEEES7_EUlvE_EONSt16remove_referenceIS6_E4typeES7_

I just haven't had time to analyze why. If someone could trace through these and see why some components have to be printed up to 3 times (or more?) that would be helpful.
Comment 43 Mark Wielaard 2017-03-02 10:12:00 UTC
See also this discussion on gcc-patches:
https://gcc.gnu.org/ml/gcc-patches/2017-03/msg00089.html
Comment 44 Markus Trippelsdorf 2017-03-08 14:29:10 UTC
Author: trippels
Date: Wed Mar  8 14:28:38 2017
New Revision: 245978

URL: https://gcc.gnu.org/viewcvs?rev=245978&root=gcc&view=rev
Log:
Fix PR demangler/70909 and 67264 (endless demangler recursion)

ChangeLog:

       PR demangler/70909
       PR demangler/67264
       * include/demangle.h: Add d_printing to struct demangle_component
       and pass struct demangle_component as non const.

libiberty/ChangeLog:

       PR demangler/70909
       PR demangler/67264
       * cp-demangle.c: Fix endless recursion. Pass
       struct demangle_component as non const.
       (d_make_empty): Initialize variable.
       (d_print_comp_inner): Limit recursion.
       (d_print_comp): Decrement variable.
       * cp-demint.c (cplus_demangle_fill_component): Initialize
       variable.
       (cplus_demangle_fill_builtin_type): Likewise.
       (cplus_demangle_fill_operator): Likewise.
       * testsuite/demangle-expected: Add tests.

Modified:
    trunk/ChangeLog
    trunk/include/demangle.h
    trunk/libiberty/ChangeLog
    trunk/libiberty/cp-demangle.c
    trunk/libiberty/cp-demint.c
    trunk/libiberty/testsuite/demangle-expected
Comment 45 Markus Trippelsdorf 2017-03-08 14:30:36 UTC
Fixed.
Comment 46 Avi Kivity 2017-03-08 15:10:55 UTC
Hopefully, the fix can be propagated to gdb's demangler soon.
Comment 47 Markus Trippelsdorf 2017-03-08 15:13:17 UTC
(In reply to Avi Kivity from comment #46)
> Hopefully, the fix can be propagated to gdb's demangler soon.

Unfortunately binutils 2.28 was released a few days ago.
The next release will be in August and will include the fix.
Comment 48 Pedro Alves 2017-03-08 15:26:48 UTC
GDB is released separately from binutils though, and GDB 8.0 is going to branch very soon.  IWBN to have this in the binutils-gdb repo by then.
Comment 49 Mark Wielaard 2017-03-12 15:42:58 UTC
(In reply to Pedro Alves from comment #48)
> GDB is released separately from binutils though, and GDB 8.0 is going to
> branch very soon.  IWBN to have this in the binutils-gdb repo by then.

Trying to integrate this into binutils-gdb produces a large number of unexpected failures in the gdb testsuite.

Some of these failures seem for previous issues handling infinite recursion or crashes when printing types. So there seems to be some conflict now with the new approach in the demangler. e.g. the following gdb testcases fail with this patch applied:

- gdb.cp/pr9167.exp
- gdb.cp/pr17132.exp
- gdb.dwarf2/pr11465.exp
- gdb.dwarf2/dw4-sig-types.exp (sourceware PR11942)
- gdb.cp/baseenum.exp (sourceware PR13615)
- gdb.cp/typeid.exp (sourceware PR9065)
Comment 50 Mark Wielaard 2017-03-12 16:29:12 UTC
(In reply to Mark Wielaard from comment #49)
> (In reply to Pedro Alves from comment #48)
> > GDB is released separately from binutils though, and GDB 8.0 is going to
> > branch very soon.  IWBN to have this in the binutils-gdb repo by then.
> 
> Trying to integrate this into binutils-gdb produces a large number of
> unexpected failures in the gdb testsuite.

This is caused by gdb doing its own memory management to reuse demangle_components. Whenever gdb d_grabs a new struct demangle_component we now need to initialize d_printing to zero.

diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y
index fd1e949..c997f20 100644
--- a/gdb/cp-name-parser.y
+++ b/gdb/cp-name-parser.y
@@ -190,6 +190,7 @@ fill_comp (enum demangle_component_type d_type, struct demangle_component *lhs,
   struct demangle_component *ret = d_grab ();
   int i;
 
+  ret->d_printing = 0;
   i = cplus_demangle_fill_component (ret, d_type, lhs, rhs);
   gdb_assert (i);
 
@@ -201,6 +202,7 @@ make_empty (enum demangle_component_type d_type)
 {
   struct demangle_component *ret = d_grab ();
   ret->type = d_type;
+  ret->d_printing = 0;
   return ret;
 }
 
@@ -210,6 +212,7 @@ make_operator (const char *name, int args)
   struct demangle_component *ret = d_grab ();
   int i;
 
+  ret->d_printing = 0;
   i = cplus_demangle_fill_operator (ret, name, args);
   gdb_assert (i);
 
@@ -222,6 +225,7 @@ make_dtor (enum gnu_v3_dtor_kinds kind, struct demangle_component *name)
   struct demangle_component *ret = d_grab ();
   int i;
 
+  ret->d_printing = 0;
   i = cplus_demangle_fill_dtor (ret, kind, name);
   gdb_assert (i);
 
@@ -234,6 +238,7 @@ make_builtin_type (const char *name)
   struct demangle_component *ret = d_grab ();
   int i;
 
+  ret->d_printing = 0;
   i = cplus_demangle_fill_builtin_type (ret, name);
   gdb_assert (i);
 
@@ -246,6 +251,7 @@ make_name (const char *name, int len)
   struct demangle_component *ret = d_grab ();
   int i;
 
+  ret->d_printing = 0;
   i = cplus_demangle_fill_name (ret, name, len);
   gdb_assert (i);
 

But maybe the cplus_demangle_fill_xxx functions should do this initializing instead? In that case gdb only needs to handle initializing d_printing for its own make_empty function.
Comment 51 Mark Wielaard 2017-03-12 22:09:36 UTC
(In reply to Mark Wielaard from comment #50)
> (In reply to Mark Wielaard from comment #49)
> > (In reply to Pedro Alves from comment #48)
> > > GDB is released separately from binutils though, and GDB 8.0 is going to
> > > branch very soon.  IWBN to have this in the binutils-gdb repo by then.
> > 
> > Trying to integrate this into binutils-gdb produces a large number of
> > unexpected failures in the gdb testsuite.
> 
> This is caused by gdb doing its own memory management to reuse
> demangle_components. Whenever gdb d_grabs a new struct demangle_component we
> now need to initialize d_printing to zero.
> [...]
> But maybe the cplus_demangle_fill_xxx functions should do this initializing
> instead? In that case gdb only needs to handle initializing d_printing for
> its own make_empty function.

yeah, I am convinced that is the more correct approach. Proposed patch:
https://gcc.gnu.org/ml/gcc-patches/2017-03/msg00622.html
Comment 52 Pedro Alves 2017-03-13 10:43:26 UTC
(In reply to Mark Wielaard from comment #51)
> (In reply to Mark Wielaard from comment #50)
> > But maybe the cplus_demangle_fill_xxx functions should do this initializing
> > instead? In that case gdb only needs to handle initializing d_printing for
> > its own make_empty function.
> 
> yeah, I am convinced that is the more correct approach. Proposed patch:
> https://gcc.gnu.org/ml/gcc-patches/2017-03/msg00622.html

Agreed.
Comment 53 Mark Wielaard 2017-04-21 09:02:35 UTC
Author: mark
Date: Fri Apr 21 09:02:03 2017
New Revision: 247056

URL: https://gcc.gnu.org/viewcvs?rev=247056&root=gcc&view=rev
Log:
libiberty: Limit demangler maximum d_print_comp recursion call depth.

The fix for PR demangler/70909 and 67264 (endless demangler recursion)
catches when a demangle_component is printed in a cycle. But that doesn't
protect the call stack blowing up from non-cyclic nested types printed
recursively through d_print_comp. This can happen by a (very) long mangled
string that simply creates a very deep pointer or qualifier chain. Limit
the recursive d_print_comp call depth for a d_print_info to 1K nested
types.

libiberty/ChangeLog:

        * cp-demangle.c (MAX_RECURSION_COUNT): New constant.
        (struct d_print_info): Add recursion field.
        (d_print_init): Initialize recursion.
        (d_print_comp): Check and update d_print_info recursion depth.

Modified:
    trunk/libiberty/ChangeLog
    trunk/libiberty/cp-demangle.c