Hi,

This fixes several stack overflows due to infinite recursion in d_print_comp 
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70909).

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. The patch uses the component stack to find 
whether the current node dc has itself as ancestor more than once. 

Bootstrapped and regression tested on x86_64-pc-linux-gnu. Test cases added to 
libiberty/testsuite/demangler-expected and checked PR70909 and related stack 
overflows are resolved.

Best regards,
- Marcel



Index: ChangeLog
===================================================================
--- ChangeLog   (revision 235760)
+++ ChangeLog   (working copy)
@@ -1,3 +1,19 @@
+2016-05-02  Marcel Böhme  <boehme.mar...@gmail.com>
+
+       PR c++/70909
+       PR c++/61460
+       PR c++/68700
+       PR c++/67738
+       PR c++/68383
+       PR c++/70517
+       PR c++/61805
+       PR c++/62279
+       PR c++/67264
+       * cp-demangle.c: Prevent infinite recursion when traversing cyclic
+       demangle component.
+       (d_print_comp): Return when demangle component has itself as ancistor
+       more than once.
+
 2016-04-30  Oleg Endo  <olege...@gcc.gnu.org>
 
        * configure: Remove SH5 support.
Index: cp-demangle.c
===================================================================
--- cp-demangle.c       (revision 235760)
+++ cp-demangle.c       (working copy)
@@ -5436,6 +5436,24 @@ d_print_comp (struct d_print_info *dpi, int option
 {
   struct d_component_stack self;
 
+  self.parent = dpi->component_stack;
+
+  while (self.parent)
+    {
+      self.dc = self.parent->dc;
+      self.parent = self.parent->parent;
+      if (dc != NULL && self.dc == dc)
+       {
+         while (self.parent)
+           {
+             self.dc = self.parent->dc;
+             self.parent = self.parent->parent;
+             if (self.dc == dc)
+               return;
+           }
+       }
+    }
+
   self.dc = dc;
   self.parent = dpi->component_stack;
   dpi->component_stack = &self;
Index: testsuite/demangle-expected
===================================================================
--- testsuite/demangle-expected (revision 235760)
+++ testsuite/demangle-expected (working copy)
@@ -4431,3 +4431,69 @@ _Q.__0
 
 _Q10-__9cafebabe.
 cafebabe.::-(void)
+#
+# Test demangler crash PR62279
+
+_ZN5Utils9transformIPN15ProjectExplorer13BuildStepListEZNKS1_18BuildConfiguration14knownStepListsEvEUlS3_E_EE5QListIDTclfp0_cvT__EEEERKS6_IS7_ET0_
+QList<decltype ({parm#2}((ProjectExplorer::BuildStepList*)()))> 
Utils::transform<ProjectExplorer::BuildStepList*, 
ProjectExplorer::BuildConfiguration::knownStepLists() 
const::{lambda(ProjectExplorer::BuildStepList*)#1}>(ProjectExplorer::BuildConfiguration::knownStepLists()
 const::{lambda(ProjectExplorer::BuildStepList*)#1}<QList> const&, 
ProjectExplorer::BuildConfiguration::knownStepLists() 
const::{lambda(ProjectExplorer::BuildStepList*)#1})
+#
+
+_ZSt7forwardIKSaINSt6thread5_ImplISt12_Bind_simpleIFZN6WIM_DL5Utils9AsyncTaskC4IMNS3_8Hardware12FpgaWatchdogEKFvvEIPS8_EEEibOT_DpOT0_EUlvE_vEEEEEESD_RNSt16remove_referenceISC_E4typeE
+std::allocator<std::thread::_Impl<std::_Bind_simple<WIM_DL::Utils::AsyncTask::AsyncTask<void
 (WIM_DL::Hardware::FpgaWatchdog::*)() const, 
WIM_DL::Hardware::FpgaWatchdog*>(int, bool, void 
(WIM_DL::Hardware::FpgaWatchdog::*&&)() const, 
WIM_DL::Hardware::FpgaWatchdog*&&)::{lambda()#1} ()> > > const&& 
std::forward<std::allocator<std::thread::_Impl<std::_Bind_simple<WIM_DL::Utils::AsyncTask::AsyncTask<void
 (WIM_DL::Hardware::FpgaWatchdog::*)() const, 
WIM_DL::Hardware::FpgaWatchdog*>(int, bool, 
std::allocator<std::thread::_Impl<std::_Bind_simple<WIM_DL::Utils::AsyncTask::AsyncTask<void
 (WIM_DL::Hardware::FpgaWatchdog::*)() const, 
WIM_DL::Hardware::FpgaWatchdog*>(int, bool, void 
(WIM_DL::Hardware::FpgaWatchdog::*&&)() const, 
WIM_DL::Hardware::FpgaWatchdog*&&)::{lambda()#1} ()> > > const&&, 
WIM_DL::Hardware::FpgaWatchdog*&&)::{lambda()#1} ()> > > 
const>(std::remove_reference<std::allocator<std::thread::_Impl<std::_Bind_simple<WIM_DL::Utils::AsyncTask::AsyncTask<void
 (WIM_DL::Hardware::FpgaWatchdog::*)() const, 
WIM_DL::Hardware::FpgaWatchdog*>(int, bool, void 
(WIM_DL::Hardware::FpgaWatchdog::*&&)() const, 
WIM_DL::Hardware::FpgaWatchdog*&&)::{lambda()#1} ()> > > const>::type&)
+#
+# Test demangler crash PR61805
+
+_ZNK5niven5ColorIfLi4EEdvIfEENSt9enable_ifIXsrSt13is_arithmeticIT_E5valueEKNS0_IDTmlcvS5__Ecvf_EELi4EEEE4typeES5_
+std::enable_if<std::is_arithmetic<float>::value, niven::Color<decltype 
(((float)())*((float)())), 4> const>::type niven::Color<float, 
4>::operator/<float>(float) const
+#
+# Test recursion PR70517
+
+_ZSt4moveIRZN11tconcurrent6futureIvE4thenIZ5awaitIS2_EDaOT_EUlRKS6_E_EENS1_INSt5decayIDTclfp_defpTEEE4typeEEES7_EUlvE_EONSt16remove_referenceIS6_E4typeES7_
+std::remove_reference<tconcurrent::future<std::decay<decltype 
({parm#1}(*this))>::type> tconcurrent::future<void>::then<auto 
await<tconcurrent::future<void> 
>(tconcurrent::future<void>&&)::{lambda(tconcurrent::future<std::decay<decltype 
({parm#1}(*this))>::type> tconcurrent::future<void>::then<auto 
await<tconcurrent::future<void> >()::{lambda( const&)#1}>( 
const)::{lambda()#1}& const&)#1}>(auto await<tconcurrent::future<void> 
>()::{lambda( const&)#1}&& const)::{lambda()#1}&>::type&& 
std::move<tconcurrent::future<std::decay<decltype ({parm#1}(*this))>::type> 
tconcurrent::future<void>::then<auto await<tconcurrent::future<void> 
>(tconcurrent::future<std::decay<decltype ({parm#1}(*this))>::type> 
tconcurrent::future<void>::then<auto await<tconcurrent::future<void> 
>(tconcurrent::future<void>&&)::{lambda(& const&)#1}>(auto 
await<tconcurrent::future<void> >()::{lambda( const&)#1}&& 
const)::{lambda()#1}&)::{lambda(tconcurrent::future<std::decay<decltype 
({parm#1}(*this))>::type> tconcurrent::future<void>::then<auto 
await<tconcurrent::future<void> >(tconcurrent::future<void>&&)::{lambda(& 
const&)#1}>(auto await<tconcurrent::future<void> >()::{lambda(&)#1}&& 
const)::{lambda()#1}& const&)#1}>(tconcurrent::future<std::decay<decltype 
({parm#1}(*this))>::type> tconcurrent::future<void>::then<auto 
await<tconcurrent::future<void> >(tconcurrent::future<void>&&)::{lambda(& 
const&)#1}>(auto await<tconcurrent::future<void> >()::{lambda(&)#1}&& 
const)::{lambda()#1}& 
const)::{lambda()#1}&>(tconcurrent::future<std::decay<decltype 
({parm#1}(*this))>::type> tconcurrent::future<void>::then<auto 
await<tconcurrent::future<void> 
>(tconcurrent::future<void>&&)::{lambda(tconcurrent::future<std::decay<decltype 
({parm#1}(*this))>::type> tconcurrent::future<void>::then<auto 
await<tconcurrent::future<void> >()::{lambda(&)#1}>()::{lambda()#1}& 
const&)#1}>(auto await<tconcurrent::future<void> >()::{lambda(&)#1}&& 
const)::{lambda()#1}& const)
+#
+# Test recursion PR68383
+
+_ZSt7forwardIRKZN5Write14DataMapGrammarISt20back_insert_iteratorISsEEC4EvEUlRT_E_EOS5_RNSt16remove_referenceIS5_E4typeE
+_ZSt7forwardIRKZN5Write14DataMapGrammarISt20back_insert_iteratorISsEEC4EvEUlRT_E_EOS5_RNSt16remove_referenceIS5_E4typeE
+#
+# Test recursion PR67264
+
+_Z1KIStcvT_E
+K<std::operator std::operator >
+
+_ZcvT_IIS0_EE
+operator operator <operator operator >
+
+_ZcvT_IZcvT_E1fE
+operator operator operator ::f::f<operator operator ::f::f>
+
+_Z1gINcvT_EE
+g<operator operator >
+
+_ZcvT_ILZcvDTT_EEE
+operator operator decltype (operator decltype ())<operator decltype (operator 
decltype ())>
+
+_Z1gIJOOT_EEOT_c
+_Z1gIJOOT_EEOT_c
+
+_Z1KMMMMMMMMMMMMMMMA_xooooooooooooooo
+K(unsigned __int128 unsigned __int128 unsigned __int128 unsigned __int128 
unsigned __int128 unsigned __int128 unsigned __int128 unsigned __int128 
unsigned __int128 unsigned __int128 unsigned __int128 unsigned __int128 
unsigned __int128 unsigned __int128 unsigned __int128 long long (long long 
(unsigned __int128 ::*::* unsigned __int128 unsigned __int128 ::*::*::* 
unsigned __int128 unsigned __int128 unsigned __int128 ::*::*::*::* unsigned 
__int128 unsigned __int128 unsigned __int128 unsigned __int128 ::*::*::*::*::* 
unsigned __int128 unsigned __int128 unsigned __int128 unsigned __int128 
unsigned __int128 ::*::*::*::*::*::* unsigned __int128 unsigned __int128 
unsigned __int128 unsigned __int128 unsigned __int128 unsigned __int128 
::*::*::*::*::*::*::* unsigned __int128 unsigned __int128 unsigned __int128 
unsigned __int128 unsigned __int128 unsigned __int128 unsigned __int128 
::*::*::*::*::*::*::*::* unsigned __int128 unsigned __int128 unsigned __int128 
unsigned __int128 unsigned __int128 unsigned __int128 unsigned __int128 
unsigned __int128 ::*::*::*::*::*::*::*::*::* unsigned __int128 unsigned 
__int128 unsigned __int128 unsigned __int128 unsigned __int128 unsigned 
__int128 unsigned __int128 unsigned __int128 unsigned __int128 
::*::*::*::*::*::*::*::*::*::* unsigned __int128 unsigned __int128 unsigned 
__int128 unsigned __int128 unsigned __int128 unsigned __int128 unsigned 
__int128 unsigned __int128 unsigned __int128 unsigned __int128 
::*::*::*::*::*::*::*::*::*::*::* unsigned __int128 unsigned __int128 unsigned 
__int128 unsigned __int128 unsigned __int128 unsigned __int128 unsigned 
__int128 unsigned __int128 unsigned __int128 unsigned __int128 unsigned 
__int128 ::*::*::*::*::*::*::*::*::*::*::*::* unsigned __int128 unsigned 
__int128 unsigned __int128 unsigned __int128 unsigned __int128 unsigned 
__int128 unsigned __int128 unsigned __int128 unsigned __int128 unsigned 
__int128 unsigned __int128 unsigned __int128 
::*::*::*::*::*::*::*::*::*::*::*::*::* unsigned __int128 unsigned __int128 
unsigned __int128 unsigned __int128 unsigned __int128 unsigned __int128 
unsigned __int128 unsigned __int128 unsigned __int128 unsigned __int128 
unsigned __int128 unsigned __int128 unsigned __int128 
::*::*::*::*::*::*::*::*::*::*::*::*::*::* unsigned __int128 unsigned __int128 
unsigned __int128 unsigned __int128 unsigned __int128 unsigned __int128 
unsigned __int128 unsigned __int128 unsigned __int128 unsigned __int128 
unsigned __int128 unsigned __int128 unsigned __int128 unsigned __int128 
::*::*::*::*::*::*::*::*::*::*::*::*::*::*::*) []::*) 
[]::*::*::*::*::*::*::*::*::*::*::*::*::*::*::*)
+
+_ZdvMMMMMMMMMMMMMrrrrA_DTdvfp_fp_Eededilfdfdfdfd
+operator/(float double float double float double float long int double long 
double double long double decltype ({parm#1}/{parm#1}) restrict (decltype 
({parm#1}/{parm#1}) restrict (long double ::*::* double long double ::*::*::* 
long double double long double ::*::*::*::* double long double double long 
double ::*::*::*::*::* int double long double double long double 
::*::*::*::*::*::* long int double long double double long double 
::*::*::*::*::*::*::* float long int double long double double long double 
::*::*::*::*::*::*::*::* double float long int double long double double long 
double ::*::*::*::*::*::*::*::*::* float double float long int double long 
double double long double ::*::*::*::*::*::*::*::*::*::* double float double 
float long int double long double double long double 
::*::*::*::*::*::*::*::*::*::*::* float double float double float long int 
double long double double long double ::*::*::*::*::*::*::*::*::*::*::*::* 
double float double float double float long int double long double double long 
double ::*::*::*::*::*::*::*::*::*::*::*::*::*) []::*) 
[]::*::*::*::*::*::*::*::*::*::*::*::*::*, double)
+#
+# Test for Infinite Recursion PR67738
+
+_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
+#
+# Test for Infinite Recursion PR68700
+
+_ZN8futurizeI13frozen_schemaE5applyIRZN7seastar7shardedIN7service13storage_proxyEE9invoke_onIZZNS6_22init_messaging_serviceEvENKUljN5utils4UUIDEE8_clEjSA_EUlOT_E_6futureIJS0_EEEET0_jSD_EUlvE_JEEESG_SD_DpOT0_
+_ZN8futurizeI13frozen_schemaE5applyIRZN7seastar7shardedIN7service13storage_proxyEE9invoke_onIZZNS6_22init_messaging_serviceEvENKUljN5utils4UUIDEE8_clEjSA_EUlOT_E_6futureIJS0_EEEET0_jSD_EUlvE_JEEESG_SD_DpOT0_
+#
+# Test for Infinite Recursion PR61460
+
+_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
+

Reply via email to