
Demangling C++ Symbols in Rust - andrew3726
http://fitzgeraldnick.com/2017/02/22/cpp-demangle.html
======
kbenson
_Tom Tromey, a GNU hacker and buddy of mine, mentioned that historically, the
canonical C++ demangler in libiberty (used by c++filt and gdb) has had tons of
classic C bugs: use-after-free, out-of-bounds array accesses, etc, and that it
falls over immediately when faced with a fuzzer. In fact, there were so many
of these issues that gdb went so far as to install a signal handler to catch
SIGSEGVs during demangling. It “recovered” from the segfaults by longjmping
out of the signal handler and printing a warning message before moving along
and pretending that nothing happened. My ears perked up. Those are the exact
kinds of things Rust protects us from at compile time! A robust alternative
might actually be a boon not just for the Rust community, but everybody who
wants to demangle C++ symbols._

Then, later:

 _Additionally, I’ve been running American Fuzzy Lop (with afl.rs) on
cpp_demangle overnight. It found a panic involving unhandled integer overflow,
which I fixed. Since then, AFL hasn’t triggered any panics, and its never been
able to find a crash (thanks Rust!) so I think cpp_demangle is fairly solid
and robust._

That's what I like to see. Targeted useful reimplementations in Rust that play
well to its strengths. In this case, as a double benefit to both the Rust
ecosystem and to anyone that wants a robust demangling library.

------
nly
LLVMs libcxxabi has a demangler which doesn't have the worst looking code in
the world[0], has no external dependencies (outside of the C++ standard
library), has lately been fuzzed[1] and is tested[2].

Switching languages is cool, but the Rust code is actually longer and still
uses a hand written parser, so how can you be sure it is any more _correct_ or
won't eat all your memory?

[0] [http://llvm.org/viewvc/llvm-
project/libcxxabi/trunk/src/cxa_...](http://llvm.org/viewvc/llvm-
project/libcxxabi/trunk/src/cxa_demangle.cpp?revision=293638&view=markup)

[1] [http://llvm.org/viewvc/llvm-
project/libcxxabi/trunk/fuzz/cxa...](http://llvm.org/viewvc/llvm-
project/libcxxabi/trunk/fuzz/cxa_demangle_fuzzer.cpp?revision=290650&view=markup)

[2] [http://llvm.org/viewvc/llvm-
project/libcxxabi/trunk/test/tes...](http://llvm.org/viewvc/llvm-
project/libcxxabi/trunk/test/test_demangle.pass.cpp?revision=293638&view=markup)

~~~
roca
It's true that one can't be sure the Rust version is "any more correct and
won't eat all your memory".

However, an even more important question is how many exploitable bugs remain
in the LLVM library vs the Rust library. The data suggests that the answer for
Rust is zero but the answer for LLVM is greater than zero.

~~~
pcwalton
> The data suggests that the answer for Rust is zero but the answer for LLVM
> is greater than zero.

Well, it's been fuzzed, so there's a pretty decent chance that the LLVM code
has zero exploitable flaws. Also, the C++ demangler isn't as security-
sensitive as many other more important projects.

That said, as a general rule raw C-style string parsing, which that C++ code
is an example of, is asking for trouble. It's painful to write, painful to
maintain, painful to debug, and, when it fails, fails in the worst possible
way. In my opinion there's little benefit to using C++ for these workloads.

~~~
gens
>That said, as a general rule raw C-style string parsing, which that C++ code
is an example of, is asking for trouble. It's painful to write, painful to
maintain, painful to debug, and, when it fails, fails in the worst possible
way. In my opinion there's little benefit to using C++ for these workloads.

AFAIK Valgrind can catch many memory access related errors. And static
analyzers can point out where such errors could happen.

From a different perspective: Why don't people do pascal stile strings with C
or C++ (and such) ? I think even i could make a library that does all the
string.h things but with length-prefixed strings. People have been complaining
for years now about C stile strings (that have been widely used for decades
now). But nobody ever did anything about it ?

PS I, myself, don't find it "painful" to use C stile strings. A few basic
precautions (like using str _n_ cmp(bla,blaa,buffer_size)) and your fine. Off-
by-one is more of a problem, at least for me at night (valgrind and llvm
static analyzer point even those out).

~~~
pjmlp
> AFAIK Valgrind can catch many memory access related errors. And static
> analyzers can point out where such errors could happen.

True, but Valgrind doesn't exist in every OS that one might need to work with,
specially embedded ones, and according to Herb's talk at CppCon 2015, only 1%
of the audience was using any form of static analyisis tooling.

The world of C and C++ programming, in typical 9-5 enterprise jobs is quite
different from HN ideals about code quality.

> I think even i could make a library that does all the string.h things but
> with length-prefixed strings. People have been complaining for years now
> about C stile strings (that have been widely used for decades now). But
> nobody ever did anything about it ?

Because it takes a big effort to make such library part of ANSI C.

> PS I, myself, don't find it "painful" to use C stile strings. A few basic
> precautions (like using strncmp(bla,blaa,buffer_size)) and your fine.

You already did a possible security exploit on your example, as you need to
guarantee 100% of the time that bla and blaa sizes are always less or equal
than buffer_size.

When working with a team it suffices that another person changes your code
without accounting for this invariant.

~~~
gens
>You already did a possible security exploit on your example, as you need to
guarantee 100% of the time that bla and blaa sizes are always less or equal
than buffer_size.

bla and blaa buffer sizes, yes. I mostly string file names/paths, that have
NAME_MAX and PATH_MAX. So my excuse here is that all my buffers have the same
size (not the best excuse, i know). PS I always sanitize on input if the input
can be anything (network/ipc sockets, for example).

>True, but Valgrind doesn't exist in every OS that one might need to work
with, specially embedded ones, and according to Herb's talk at CppCon 2015,
only 1% of the audience was using any form of static analyisis tooling.

Quick google shows _some_ tools for windows. I don't know how good they are.
Clangs static analyzer seems to work on windows, for static analysis. But if
it compiles on linux/bsd/osx then people _should_ check before shipping the
code.

This just reminded me of the latest Linus rant[0].

Then there is fuzzing and formal verification, that are too much for "normal"
programs (these are not C specific).

>The world of C and C++ programming, in typical 9-5 enterprise jobs is quite
different from HN ideals about code quality.

As is in the world of hobby C and C++ programming. And python, and ruby, and
haskell, and... It just shows more in C. But C is still the king when it comes
to portable and efficient programs, and that won't change soon (although there
is less need for such programs, as "embedded" today equals "has only 512MB
RAM").

[0]
[http://lkml.iu.edu/hypermail/linux/kernel/1702.2/05171.html](http://lkml.iu.edu/hypermail/linux/kernel/1702.2/05171.html)

------
sfink
Coincidentally, I recently discovered that code I landed in the mozilla repo a
couple of weeks ago crashes gdb when it tries to demangle (and c++filt on the
command line). Looks to be infinite recursion. It's still in the current
Nightly binary.

_ZN2js18CompartmentChecker5checkIN2JS8GCVectorI4jsidLm0ENS_15TempAllocPolicyEEEEEN7mozilla8EnableIfIXsrNS7_6IsSameIDTclptcvPT_LDn0E5beginEEDTclptcvSB_LDn0E3endEEEE5valueEvE4TypeERKSA_

coming from

    
    
        template <typename Container>
        typename mozilla::EnableIf<
            mozilla::IsSame<
                decltype(((Container*)nullptr)->begin()),
                decltype(((Container*)nullptr)->end())
            >::value
        >::Type
        check(const Container& container) { ... }

~~~
ayosec
Out of curiosity, what version of c++filt are you using?

I tried with 2.27.51 (Debian), and it works:

    
    
        mozilla::EnableIf<mozilla::IsSame<decltype ((((JS::GCVector<jsid, 0ul, js::TempAllocPolicy>*)((decltype(nullptr))0))->begin)()), decltype ((((JS::GCVector<jsid, 0ul, js::TempAllocPolicy>*)((decltype(nullptr))0))->end)())>::value, void>::Type js::CompartmentChecker::check<JS::GCVector<jsid, 0ul, js::TempAllocPolicy> >(JS::GCVector<jsid, 0ul, js::TempAllocPolicy> const&)

~~~
sfink
2.26.1-1.fc25 from Fedora 25

------
pjmlp
> Linkers only support C identifiers for symbol names.

This is only true of UNIX system linkers, before the FOSS and UNIX clones
wave, it was common for each compiler to have its own language specific
linker.

~~~
Rusky
Kind of a blessing and a curse- reduces links to a common subset of
functionality, but also makes it trivial to link together code from any
languages that support the platform's C ABI.

------
shmerl
Can it help to implement C++ bindings for Rust?

~~~
steveklabnik
My understanding is that yes, this is part of that puzzle. The author of this
post works on
[https://crates.io/crates/bindgen](https://crates.io/crates/bindgen)

------
problems
How bad are the rules for MSVC compared to the Itanium ones and would you
consider adding support for it too?

Not that I have a use case in mind or anything, just curious.

~~~
jcranmer
Pretty bad, actually. There is no official documentation of the name mangling,
so everything that is known is reverse engineered. In particular, there are
outright bugs in the name mangling scheme, and one of the rules appears to
rely on hashing the function body to produce a result. I'd give you examples,
but, I don't have any of them on hand (I'm mostly relying on recollection from
conversations with David Majnemer).

~~~
twoodfin
_one of the rules appears to rely on hashing the function body to produce a
result_

Gross! I wonder what that's for. Somebody's hack to allow same-name/same-
interface header inline functions to coexist?

------
jjoonathan
> These days, almost every C++ compiler uses the Itanium C++ ABI’s name
> mangling rules. The notable exception is MSVC, which uses a completely
> different format.

You stay classy, Microsoft.

> Its not just the grammar that’s huge, the symbols themselves are too. Here
> is a pretty big mangled C++ symbol from SpiderMonkey [...] That’s 355 bytes!

Here's a >4kB symbol I encountered while liberating some ebooks from an
abandoned DRM app:

    
    
        tetraphilia::transient_ptrs<tetraphilia::imaging_model::PixelProducer<T3AppTraits> >::ptr_type tetraphilia::imaging_model::MakeIdealPixelProducer<tetraphilia::imaging_model::XWalkerCluster<tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalkerList3<tetraphilia::imaging_model::const_UnifiedGraphicXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, 0ul, 0, 1ul, 0ul, 0, 0ul, 0ul, 0, 0ul, 1ul>, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 0ul> > > >, tetraphilia::TypeList<tetraphilia::imaging_model::XWalkerCluster<tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalkerList3<tetraphilia::imaging_model::const_UnifiedGraphicXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, 0ul, 0, 1ul, 0ul, 0, 0ul, 0ul, 0, 0ul, 0ul>, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 0ul> > > >, tetraphilia::TypeList<tetraphilia::imaging_model::XWalkerCluster<tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalkerList3<tetraphilia::imaging_model::const_UnifiedGraphicXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, 0ul, 0, 1ul, 0ul, 0, 0ul, 0ul, 0, 0ul, 1ul>, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> > > >, tetraphilia::Terminal> >, T3AppTraits, tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, tetraphilia::imaging_model::SeparableOperation<tetraphilia::imaging_model::ClipOperation<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> > > >(tetraphilia::ArgType<tetraphilia::TypeList<tetraphilia::imaging_model::XWalkerCluster<tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalkerList3<tetraphilia::imaging_model::const_UnifiedGraphicXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, 0ul, 0, 1ul, 0ul, 0, 0ul, 0ul, 0, 0ul, 1ul>, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 0ul> > > >, tetraphilia::TypeList<tetraphilia::imaging_model::XWalkerCluster<tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalkerList3<tetraphilia::imaging_model::const_UnifiedGraphicXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, 0ul, 0, 1ul, 0ul, 0, 0ul, 0ul, 0, 0ul, 0ul>, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::OneXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 0ul> > > >, tetraphilia::TypeList<tetraphilia::imaging_model::XWalkerCluster<tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalkerList3<tetraphilia::imaging_model::const_UnifiedGraphicXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits>, 0ul, 0, 1ul, 0ul, 0, 0ul, 0ul, 0, 0ul, 1ul>, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> >, tetraphilia::imaging_model::GraphicXWalker<tetraphilia::imaging_model::const_IgnoredRasterXWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 0ul, 0, 1ul, 1ul>, tetraphilia::imaging_model::const_SpecializedRasterXWalker<unsigned char, 2ul, -1, 3ul, 3ul> > > >, tetraphilia::Terminal> > > >, T3AppTraits::context_type&, tetraphilia::imaging_model::Constraints<T3AppTraits> const&, tetraphilia::imaging_model::SeparableOperation<tetraphilia::imaging_model::ClipOperation<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> > >, tetraphilia::imaging_model::const_GraphicYWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> > const*, tetraphilia::imaging_model::const_GraphicYWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> > const*, tetraphilia::imaging_model::const_GraphicYWalker<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> > const*, tetraphilia::imaging_model::SegmentFactory<tetraphilia::imaging_model::ByteSignalTraits<T3AppTraits> >*)

~~~
hermitdev
If you want some huge symbols, introduce Boost Lambda into a project. Doing a
single for_each with a Boost Lambda can introduce symbols of several 100k.

~~~
jjoonathan
Nice! I'm not near a C++ environment atm, but I promise an upvote to anyone
who digs up one of these beasts for us to gawk at!

~~~
jcranmer
This is one that I found from running nm on a binary:

    
    
        _ZN5boost6detail7variant15visitation_implIN4mpl_4int_ILi40EEENS1_20visitation_impl_stepINS_3mpl6v_iterINS7_6v_itemI25SelectedEntityChangedDataNS9_IN11InputAction17ServerCommandDataENS9_INSB_18SetupBlueprintDataENS9_INSB_13BuildRailDataENS9_I2IDI20CustomInputPrototypetENS9_IN10ActionData22TrainWaitConditionDataENS9_INSI_18TrainWaitConditionENS9_INSB_22BuildTerrainParametersENS9_I27DeciderCombinatorParametersNS9_I30ArithmeticCombinatorParametersNS9_INSB_18PlayerJoinGameDataENS9_INSB_7CrcDataENS9_INSB_20SetBlueprintIconDataENS9_I20AbilitySpecificationNS9_INSB_17TakeEquipmentDataENS9_INSB_18PlaceEquipmentDataENS9_I6VectorNS9_IdNS9_ISF_I9ItemGrouphENS9_INSB_15MarketOfferDataENS9_ISsNS9_INSI_33BehaviorModeOfOperationParametersENS9_INSI_17TrainScheduleDataENS9_INSB_18GuiTextChangedDataENS9_INSB_14GuiChangedDataENS9_INSB_12GuiClickDataENS9_INSB_20SelectItemParametersENS9_INSI_24LogisticFilterSignalDataENS9_INSI_22LogisticFilterItemDataENS9_ISF_I19TechnologyPrototypetENS9_INSI_10SignalDataENS9_INSI_26CircuitConditionParametersENS9_INSB_19SetFilterParametersENS9_INSB_19BuildItemParametersENS9_INSB_16CancelCraftOrderENS9_INSB_9CraftDataENS9_I13ShootingStateNS9_IhNS9_ItNS9_IjNS9_IbNS9_ISF_I13ItemPrototypetENS9_ISF_I15RecipePrototypetENS9_I28ItemStackTargetSpecificationNS9_I11RidingStateNS9_I9DirectionNS9_INSB_14SelectAreaDataENS9_I12RealPositionNS7_7vector0INS3_2naEEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELi0EEELl40EEENS8_IS32_Ll48EEEEENS1_14invoke_visitorINS1_11get_visitorIKS10_EEEEPKvNS_7variantINS1_13over_sequenceINS7_8vector48IS1N_S1M_S1L_S1K_S1J_S1I_S1G_bjthS1E_S1D_S1C_S1B_S1A_S19_S18_S17_S15_S14_S13_S12_S11_S10_SZ_SY_SsSX_SW_dSU_ST_SS_SR_SQ_SP_SO_SN_SM_SL_SK_SJ_SH_SE_SD_SC_SA_EEEEJEE18has_fallback_type_EEENT1_11result_typeEiiRS3K_T2_NS3_5bool_ILb0EEET3_PT_PT0_
    

The c++filt output is 13,776 characters, so I can't easily copy it here.

------
bassamtabbara
There's also this one
[https://github.com/ianlancetaylor/demangle](https://github.com/ianlancetaylor/demangle)

------
phkahler
I really enjoy reading these pieces where someone rewrites something in rust
and it turns out better than the old C version due to rusts safety features.
Usually those kinds of projects are just a rewrite to someones favorite
language of the month, for little tangible benefit other than their own
satisfaction or education. These rust ones seem to show tangible benefits to
the language itself.

