diff options
author | Erik Pilkington <erik.pilkington@gmail.com> | 2018-03-26 15:34:36 +0000 |
---|---|---|
committer | Erik Pilkington <erik.pilkington@gmail.com> | 2018-03-26 15:34:36 +0000 |
commit | 0e5d196fc4f2078c083f601f0f493cee3f119481 (patch) | |
tree | 2d25d9720fd4b3cb76475d460328316d126a1c88 /libcxxabi/src | |
parent | 567efcec5ec375c2446e2da53bee20030fad30cc (diff) |
[demangler] Fix a bug in r328464 found by oss-fuzz.
Diffstat (limited to 'libcxxabi/src')
-rw-r--r-- | libcxxabi/src/cxa_demangle.cpp | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/libcxxabi/src/cxa_demangle.cpp b/libcxxabi/src/cxa_demangle.cpp index 40fba9db7d3..9253e830b18 100644 --- a/libcxxabi/src/cxa_demangle.cpp +++ b/libcxxabi/src/cxa_demangle.cpp @@ -1096,23 +1096,48 @@ struct ForwardTemplateReference : Node { size_t Index; Node *Ref = nullptr; + // If we're currently printing this node. It is possible (though invalid) for + // a forward template reference to refer to itself via a substitution. This + // creates a cyclic AST, which will stack overflow printing. To fix this, bail + // out if more than one print* function is active. + mutable bool Printing = false; + ForwardTemplateReference(size_t Index_) : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown, Cache::Unknown), Index(Index_) {} bool hasRHSComponentSlow(OutputStream &S) const override { + if (Printing) + return false; + SwapAndRestore<bool> SavePrinting(Printing, true); return Ref->hasRHSComponent(S); } bool hasArraySlow(OutputStream &S) const override { + if (Printing) + return false; + SwapAndRestore<bool> SavePrinting(Printing, true); return Ref->hasArray(S); } bool hasFunctionSlow(OutputStream &S) const override { + if (Printing) + return false; + SwapAndRestore<bool> SavePrinting(Printing, true); return Ref->hasFunction(S); } - void printLeft(OutputStream &S) const override { Ref->printLeft(S); } - void printRight(OutputStream &S) const override { Ref->printRight(S); } + void printLeft(OutputStream &S) const override { + if (Printing) + return; + SwapAndRestore<bool> SavePrinting(Printing, true); + Ref->printLeft(S); + } + void printRight(OutputStream &S) const override { + if (Printing) + return; + SwapAndRestore<bool> SavePrinting(Printing, true); + Ref->printRight(S); + } }; class NameWithTemplateArgs final : public Node { |