Hi Jason, These test cases are generated by fuzzing which produces a lot of nonsensical input data. I think, "Garbage In, Garbage Out" is quite applicable here. With the patch at least it doesn’t crash and fixes the vulnerability.
Best regards, - Marcel > On 26 May 2016, at 10:05 PM, Jason Merrill <ja...@redhat.com> wrote: > > It seems like in cases of malformed input we should return the input > again rather than produce garbage like "K<std::operator std::operator >> ". Maybe catch this sort of situation in > d_lookup_template_parameter? > > Jason > > > On Mon, May 2, 2016 at 11:21 AM, Marcel Böhme <boehme.mar...@gmail.com> wrote: >> 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 >> + >>