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.
(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?
Here: https://gcc.gnu.org/ml/gcc-patches/2016-05/msg00105.html Pending review.
These crashes are still plaguing GDB users, unfortunately. Any chance the patches make it to trunk?
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.
(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.
*** Bug 67738 has been marked as a duplicate of this bug. ***
(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.
(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&&))
(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.
(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.
(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?
(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?
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.
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).
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&)
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.
Nathan's patch fixes this issue: https://patchwork.ozlabs.org/patch/701137/ It is currently being reviewed.
(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)
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.
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.
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.
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.
Created attachment 40231 [details] Check output with d_printing.patch
(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;
(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.
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.
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.
(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.
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
(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&)
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
(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.
(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.
(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.
(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
(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
(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__ )
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).
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.
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.
(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.
(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.
See also this discussion on gcc-patches: https://gcc.gnu.org/ml/gcc-patches/2017-03/msg00089.html
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
Fixed.
Hopefully, the fix can be propagated to gdb's demangler soon.
(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.
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.
(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)
(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.
(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
(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.
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