From 615e753e09ff4d93ef067fb221433f5cb50b3c46 Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Mon, 26 Mar 2018 15:34:36 +0000 Subject: [PATCH] [demangler] Fix a bug in r328464 found by oss-fuzz. llvm-svn: 328507 --- libcxxabi/src/cxa_demangle.cpp | 29 +++++++++++++++++++++++++-- llvm/lib/Demangle/ItaniumDemangle.cpp | 29 +++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/libcxxabi/src/cxa_demangle.cpp b/libcxxabi/src/cxa_demangle.cpp index 40fba9db7d30..9253e830b180 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 SavePrinting(Printing, true); return Ref->hasRHSComponent(S); } bool hasArraySlow(OutputStream &S) const override { + if (Printing) + return false; + SwapAndRestore SavePrinting(Printing, true); return Ref->hasArray(S); } bool hasFunctionSlow(OutputStream &S) const override { + if (Printing) + return false; + SwapAndRestore 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 SavePrinting(Printing, true); + Ref->printLeft(S); + } + void printRight(OutputStream &S) const override { + if (Printing) + return; + SwapAndRestore SavePrinting(Printing, true); + Ref->printRight(S); + } }; class NameWithTemplateArgs final : public Node { diff --git a/llvm/lib/Demangle/ItaniumDemangle.cpp b/llvm/lib/Demangle/ItaniumDemangle.cpp index c80b1c9ef2bd..3f610a41422c 100644 --- a/llvm/lib/Demangle/ItaniumDemangle.cpp +++ b/llvm/lib/Demangle/ItaniumDemangle.cpp @@ -1088,23 +1088,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 SavePrinting(Printing, true); return Ref->hasRHSComponent(S); } bool hasArraySlow(OutputStream &S) const override { + if (Printing) + return false; + SwapAndRestore SavePrinting(Printing, true); return Ref->hasArray(S); } bool hasFunctionSlow(OutputStream &S) const override { + if (Printing) + return false; + SwapAndRestore 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 SavePrinting(Printing, true); + Ref->printLeft(S); + } + void printRight(OutputStream &S) const override { + if (Printing) + return; + SwapAndRestore SavePrinting(Printing, true); + Ref->printRight(S); + } }; class NameWithTemplateArgs final : public Node {