Hi all,

A patch I committed to libiberty last year [1, 2] caused a regression
that caused the demangler to segfault on certain symbols [3, 4, 5, 6].
The attached patch fixes, and adds regression tests for all symbols
referenced in those bugs.

Ok to commit?

Thanks,
Gary

--
http://gbenson.net/

[1] http://gcc.gnu.org/ml/gcc-patches/2013-09/msg01299.html
[2] http://gcc.gnu.org/ml/gcc-patches/2013-12/msg01755.html
[3] https://sourceware.org/bugzilla/show_bug.cgi?id=14963
[4] https://sourceware.org/bugzilla/show_bug.cgi?id=16593
[5] https://sourceware.org/bugzilla/show_bug.cgi?id=16752
[6] https://sourceware.org/bugzilla/show_bug.cgi?id=16845

2014-05-07  Gary Benson  <gben...@redhat.com>

        * cp-demangle.c (struct d_component_stack): New structure.
        (struct d_print_info): New field component_stack.
        (d_print_init): Initialize the above.
        (d_print_comp_inner): Renamed from d_print_comp.
        Do not restore template stack if it would cause a loop.
        (d_print_comp): New function.
        * testsuite/demangle-expected: New test cases.

diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index bf2ffa9..41c86c7 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -275,6 +275,16 @@ struct d_growable_string
   int allocation_failure;
 };
 
+/* Stack of components, innermost first, used to avoid loops.  */
+
+struct d_component_stack
+{
+  /* This component.  */
+  const struct demangle_component *dc;
+  /* This component's parent.  */
+  const struct d_component_stack *parent;
+};
+
 /* A demangle component and some scope captured when it was first
    traversed.  */
 
@@ -327,6 +337,8 @@ struct d_print_info
   int pack_index;
   /* Number of d_print_flush calls so far.  */
   unsigned long int flush_count;
+  /* Stack of components, innermost first, used to avoid loops.  */
+  const struct d_component_stack *component_stack;
   /* Array of saved scopes for evaluating substitutions.  */
   struct d_saved_scope *saved_scopes;
   /* Index of the next unused saved scope in the above array.  */
@@ -3934,6 +3946,8 @@ d_print_init (struct d_print_info *dpi, 
demangle_callbackref callback,
 
   dpi->demangle_failure = 0;
 
+  dpi->component_stack = NULL;
+
   dpi->saved_scopes = NULL;
   dpi->next_saved_scope = 0;
   dpi->num_saved_scopes = 0;
@@ -4269,8 +4283,8 @@ d_get_saved_scope (struct d_print_info *dpi,
 /* Subroutine to handle components.  */
 
 static void
-d_print_comp (struct d_print_info *dpi, int options,
-              const struct demangle_component *dc)
+d_print_comp_inner (struct d_print_info *dpi, int options,
+                 const struct demangle_component *dc)
 {
   /* Magic variable to let reference smashing skip over the next modifier
      without needing to modify *dc.  */
@@ -4673,11 +4687,30 @@ d_print_comp (struct d_print_info *dpi, int options,
              }
            else
              {
+               const struct d_component_stack *dcse;
+               int found_self_or_parent = 0;
+
                /* This traversal is reentering SUB as a substition.
-                  Restore the original templates temporarily.  */
-               saved_templates = dpi->templates;
-               dpi->templates = scope->templates;
-               need_template_restore = 1;
+                  If we are not beneath SUB or DC in the tree then we
+                  need to restore SUB's template stack temporarily.  */
+               for (dcse = dpi->component_stack; dcse != NULL;
+                    dcse = dcse->parent)
+                 {
+                   if (dcse->dc == sub
+                       || (dcse->dc == dc
+                           && dcse != dpi->component_stack))
+                     {
+                       found_self_or_parent = 1;
+                       break;
+                     }
+                 }
+
+               if (!found_self_or_parent)
+                 {
+                   saved_templates = dpi->templates;
+                   dpi->templates = scope->templates;
+                   need_template_restore = 1;
+                 }
              }
 
            a = d_lookup_template_argument (dpi, sub);
@@ -5316,6 +5349,21 @@ d_print_comp (struct d_print_info *dpi, int options,
     }
 }
 
+static void
+d_print_comp (struct d_print_info *dpi, int options,
+             const struct demangle_component *dc)
+{
+  struct d_component_stack self;
+
+  self.dc = dc;
+  self.parent = dpi->component_stack;
+  dpi->component_stack = &self;
+
+  d_print_comp_inner (dpi, options, dc);
+
+  dpi->component_stack = self.parent;
+}
+
 /* Print a Java dentifier.  For Java we try to handle encoded extended
    Unicode characters.  The C++ ABI doesn't mention Unicode encoding,
    so we don't it for C++.  Characters are encoded as
diff --git a/libiberty/testsuite/demangle-expected 
b/libiberty/testsuite/demangle-expected
index 3ff08e6..453f9a3 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -4294,6 +4294,7 @@ void n<void (A::*)() const &>(void (A::*)() const &)
 --format=gnu-v3
 _ZL1fIiEvv
 void f<int>()
+# https://sourceware.org/bugzilla/show_bug.cgi?id=14963#c3
 --format=gnu-v3
 
_ZSt7forwardIRN1x14refobjiteratorINS0_3refINS0_4mime30multipart_section_processorObjIZ15get_body_parserIZZN14mime_processor21make_section_iteratorERKNS2_INS3_10sectionObjENS0_10ptrrefBaseEEEbENKUlvE_clEvEUlSB_bE_ZZNS6_21make_section_iteratorESB_bENKSC_clEvEUlSB_E0_ENS1_INS2_INS0_20outputrefiteratorObjIiEES8_EEEERKSsSB_OT_OT0_EUlmE_NS3_32make_multipart_default_discarderISP_EEEES8_EEEEEOT_RNSt16remove_referenceISW_E4typeE
 
x::refobjiterator<x::ref<x::mime::multipart_section_processorObj<x::refobjiterator<x::ref<x::outputrefiteratorObj<int>,
 x::ptrrefBase> > 
get_body_parser<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj,
 x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}, 
mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, 
x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> 
const&)#2}>(std::string const&, x::ref<x::mime::sectionObj, x::ptrrefBase> 
const&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, 
x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&, 
mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, 
x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> 
const&)#2}&&)::{lambda(unsigned long)#1}, 
x::mime::make_multipart_default_discarder<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj,
 x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&> 
>, x::ptrrefBase> >& 
std::forward<x::refobjiterator<x::ref<x::mime::multipart_section_processorObj<x::refobjiterator<x::ref<x::outputrefiteratorObj<int>,
 x::ptrrefBase> > 
get_body_parser<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj,
 x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}, 
mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, 
x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> 
const&)#2}>(std::string const&, x::ref<x::mime::sectionObj, x::ptrrefBase> 
const&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, 
x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&, 
mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, 
x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> 
const&)#2}&&)::{lambda(unsigned long)#1}, 
x::mime::make_multipart_default_discarder<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj,
 x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&> 
>, x::ptrrefBase> 
>&>(std::remove_reference<x::mime::multipart_section_processorObj<x::refobjiterator<x::ref<x::outputrefiteratorObj<int>,
 x::ptrrefBase> > 
get_body_parser<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj,
 x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}, 
mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, 
x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> 
const&)#2}>(std::string const&, x::ref<x::mime::sectionObj, x::ptrrefBase> 
const&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, 
x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&, 
mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, 
x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> 
const&)#2}&&)::{lambda(unsigned long)#1}, 
x::mime::make_multipart_default_discarder<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj,
 x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() 
const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&> > 
>::type&)
@@ -4317,3 +4318,28 @@ A::operator C*<C>
 _ZN1AcvT_IiEI1CEEv
 A::operator C<int><C>()
 A::operator C<int><C>
+# https://sourceware.org/bugzilla/show_bug.cgi?id=14963#c16
+--format=gnu-v3
+_ZN3mdr16in_cached_threadIRZNK4cudr6GPUSet17parallel_for_eachIZN5tns3d20shape_representation7compute7GPUImpl7executeERKNS_1AINS_7ptr_refIKjEELl3ELl3ENS_8c_strideILl1ELl0EEEEERKNS8_INS9_IjEELl4ELl1ESD_EEEUliRKNS1_7ContextERNS7_5StateEE_JSt6vectorISO_SaISO_EEEEEvOT_DpRT0_EUlSP_E_JSt17reference_wrapperISO_EEEENS_12ScopedFutureIDTclfp_spcl7forwardISW_Efp0_EEEEESV_DpOSW_
+mdr::ScopedFuture<decltype ({parm#1}(((forward<void 
cudr::GPUSet::parallel_for_each<tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned
 int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, 
mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > 
const&)::{lambda(int, cudr::Context const&, 
tns3d::shape_representation::compute::GPUImpl::State&)#1}, 
std::vector<tns3d::shape_representation::compute::GPUImpl::State, 
std::allocator<tns3d::shape_representation::compute::GPUImpl::State> > 
>(tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned
 int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, 
mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > 
const&)::{lambda(int, cudr::Context const&, 
tns3d::shape_representation::compute::GPUImpl::State&)#1}&&, 
std::vector<tns3d::shape_representation::compute::GPUImpl::State, 
std::allocator<tns3d::shape_representation::compute::GPUImpl::State> >&) 
const::{lambda(tns3d::shape_representation::compute::GPUImpl::State&)#1}&>)({parm#2}))...))>
 mdr::in_cached_thread<void 
cudr::GPUSet::parallel_for_each<tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned
 int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, 
mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > 
const&)::{lambda(int, cudr::Context const&, 
tns3d::shape_representation::compute::GPUImpl::State&)#1}, 
std::vector<tns3d::shape_representation::compute::GPUImpl::State, 
std::allocator<tns3d::shape_representation::compute::GPUImpl::State> > >(void 
cudr::GPUSet::parallel_for_each<tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned
 int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, 
mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > 
const&)::{lambda(int, cudr::Context const&, 
tns3d::shape_representation::compute::GPUImpl::State&)#1}, 
std::vector<tns3d::shape_representation::compute::GPUImpl::State, 
std::allocator<tns3d::shape_representation::compute::GPUImpl::State> > 
>(tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned
 int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, 
mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > 
const&)::{lambda(int, cudr::Context const&, 
tns3d::shape_representation::compute::GPUImpl::State&)#1}&&, 
std::vector<tns3d::shape_representation::compute::GPUImpl::State, 
std::allocator<tns3d::shape_representation::compute::GPUImpl::State> >&) 
const::{lambda(tns3d::shape_representation::compute::GPUImpl::State&)#1}&, 
std::vector<tns3d::shape_representation::compute::GPUImpl::State, 
std::allocator<tns3d::shape_representation::compute::GPUImpl::State> >&) 
const::{lambda(tns3d::shape_representation::compute::GPUImpl::State&)#1}&, 
std::reference_wrapper<tns3d::shape_representation::compute::GPUImpl::State> 
>(void 
cudr::GPUSet::parallel_for_each<tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned
 int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, 
mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > 
const&)::{lambda(int, cudr::Context const&, 
tns3d::shape_representation::compute::GPUImpl::State&)#1}, 
std::vector<tns3d::shape_representation::compute::GPUImpl::State, 
std::allocator<tns3d::shape_representation::compute::GPUImpl::State> > 
>(tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned
 int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, 
mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > 
const&)::{lambda(int, cudr::Context const&, 
tns3d::shape_representation::compute::GPUImpl::State&)#1}&&, 
std::vector<tns3d::shape_representation::compute::GPUImpl::State, 
std::allocator<tns3d::shape_representation::compute::GPUImpl::State> >&) 
const::{lambda(tns3d::shape_representation::compute::GPUImpl::State&)#1}&, 
(void 
cudr::GPUSet::parallel_for_each<tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned
 int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, 
mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > 
const&)::{lambda(int, cudr::Context const&, 
tns3d::shape_representation::compute::GPUImpl::State&)#1}, 
std::vector<tns3d::shape_representation::compute::GPUImpl::State, 
std::allocator<tns3d::shape_representation::compute::GPUImpl::State> > 
>(tns3d::shape_representation::compute::GPUImpl::execute(mdr::A<mdr::ptr_ref<unsigned
 int const>, 3l, 3l, mdr::c_stride<1l, 0l> > const&, 
mdr::A<mdr::ptr_ref<unsigned int>, 4l, 1l, mdr::c_stride<1l, 0l> > 
const&)::{lambda(int, cudr::Context const&, 
tns3d::shape_representation::compute::GPUImpl::State&)#1}&&, 
std::vector<tns3d::shape_representation::compute::GPUImpl::State, 
std::allocator<tns3d::shape_representation::compute::GPUImpl::State> >&) 
const::{lambda(tns3d::shape_representation::compute::GPUImpl::State&)#1}&&&)...)
+# https://sourceware.org/bugzilla/show_bug.cgi?id=14963#c18
+--format=gnu-v3
+_ZNSt9_Any_data9_M_accessIPZN13ThreadManager10futureTaskISt5_BindIFSt7_Mem_fnIM6RunnerFvvEEPS5_EEEEvOT_EUlvE_EERSC_v
+void ThreadManager::futureTask<std::_Bind<std::_Mem_fn<void (Runner::*)()> 
(Runner*)> >(std::_Bind<std::_Mem_fn<void (Runner::*)()> 
(Runner*)>&&)::{lambda()#1}*& std::_Any_data::_M_access<void 
ThreadManager::futureTask<std::_Bind<std::_Mem_fn<void (Runner::*)()> 
(Runner*)> >(void ThreadManager::futureTask<std::_Bind<std::_Mem_fn<void 
(Runner::*)()> (Runner*)> >(std::_Bind<std::_Mem_fn<void (Runner::*)()> 
(Runner*)>&&)::{lambda()#1}*&&)::{lambda()#1}*>()
+# https://sourceware.org/bugzilla/show_bug.cgi?id=14963#c24
+# aka https://sourceware.org/bugzilla/show_bug.cgi?id=16593
+--format=gnu-v3
+_ZNSt9_Any_data9_M_accessIPZN3sel8Selector6SetObjI3FooJPKcMS4_FviEEEEvRT_DpT0_EUlvE_EESA_v
+void sel::Selector::SetObj<Foo, char const*, void (Foo::*)(int)>(Foo&, char 
const*, void (Foo::*)(int))::{lambda()#1}*& std::_Any_data::_M_access<void 
sel::Selector::SetObj<Foo, char const*, void (Foo::*)(int)>(void 
sel::Selector::SetObj<Foo, char const*, void (Foo::*)(int)>(Foo&, char const*, 
void (Foo::*)(int))::{lambda()#1}*&, char const*, void 
(Foo::*)(int))::{lambda()#1}*>()
+# https://sourceware.org/bugzilla/show_bug.cgi?id=16752#c1
+--format=gnu-v3
+_ZNSt9_Any_data9_M_accessIPZN13ThreadManager7newTaskIRSt5_BindIFSt7_Mem_fnIM5DiaryFivEEPS5_EEIEEESt6futureINSt9result_ofIFT_DpT0_EE4typeEEOSF_DpOSG_EUlvE_EERSF_v
+std::future<std::result_of<std::_Bind<std::_Mem_fn<int (Diary::*)()> 
(Diary*)>& ()>::type> ThreadManager::newTask<std::_Bind<std::_Mem_fn<int 
(Diary::*)()> (Diary*)>&>(std::_Bind<std::_Mem_fn<int (Diary::*)()> 
(Diary*)>&)::{lambda()#1}*& 
std::_Any_data::_M_access<std::future<std::result_of<std::_Bind<std::_Mem_fn<int
 (Diary::*)()> (Diary*)>& ()>::type> 
ThreadManager::newTask<std::_Bind<std::_Mem_fn<int (Diary::*)()> 
(Diary*)>&>(std::future<std::result_of<std::_Bind<std::_Mem_fn<int 
(Diary::*)()> (Diary*)>& ()>::type> 
ThreadManager::newTask<std::_Bind<std::_Mem_fn<int (Diary::*)()> 
(Diary*)>&>(std::_Bind<std::_Mem_fn<int (Diary::*)()> 
(Diary*)>&)::{lambda()#1}*&&)::{lambda()#1}*>()
+# https://sourceware.org/bugzilla/show_bug.cgi?id=16752#c6
+--format=gnu-v3
+_ZNSt9_Any_data9_M_accessIPZN6cereal18polymorphic_detail15getInputBindingINS1_16JSONInputArchiveEEENS1_6detail15InputBindingMapIT_E11SerializersERS7_jEUlPvRSt10unique_ptrIvNS5_12EmptyDeleterIvEEEE0_EESA_v
+cereal::detail::InputBindingMap<cereal::JSONInputArchive>::Serializers 
cereal::polymorphic_detail::getInputBinding<cereal::JSONInputArchive>(cereal::JSONInputArchive&,
 unsigned int)::{lambda(void*, std::unique_ptr<void, 
cereal::detail::EmptyDeleter<void> >&)#2}*& 
std::_Any_data::_M_access<cereal::detail::InputBindingMap<cereal::JSONInputArchive>::Serializers
 
cereal::polymorphic_detail::getInputBinding<cereal::JSONInputArchive>(cereal::detail::InputBindingMap<cereal::JSONInputArchive>::Serializers
 
cereal::polymorphic_detail::getInputBinding<cereal::JSONInputArchive>(cereal::JSONInputArchive&,
 unsigned int)::{lambda(void*, std::unique_ptr<void, 
cereal::detail::EmptyDeleter<void> >&)#2}*&, unsigned int)::{lambda(void*, 
std::unique_ptr<void, cereal::detail::EmptyDeleter<void> >&)#2}*>()
+# https://sourceware.org/bugzilla/show_bug.cgi?id=16845#c2
+--format=gnu-v3
+_ZNSt9_Any_data9_M_accessIPZ4postISt8functionIFvvEEEvOT_EUlvE_EERS5_v
+void post<std::function<void ()> >(std::function<void ()>&&)::{lambda()#1}*& 
std::_Any_data::_M_access<void post<std::function<void ()> >(void 
post<std::function<void ()> >(std::function<void 
()>&&)::{lambda()#1}*&&)::{lambda()#1}*>()

Reply via email to