Opened 4 years ago

Closed 4 years ago

#13561 closed Bugs (fixed)

boost::detail::nullary_function causes stack overflow when copied

Reported by: yhirsch@… Owned by: viboes
Milestone: Boost 1.69 Component: thread
Version: Boost 1.67.0 Severity: Showstopper
Keywords: stack, overflow, thread, future, nullary, function Cc:

Description

Hi,

It seems as though boost::detail::nullary_function implement a perfect forwarding constructor incorrectly, which causes a stack overflow:

Here is a simple example:

#include <boost/thread/detail/nullary_function.hpp>
#include <boost/system/detail/error_code.ipp>

int main(int argc, char* argv[])
{
    boost::detail::nullary_function<void ()> f1;
    auto f2 = f1;
}

This ends up invoking nullary_function.hpp:81 which keeps invoking iself recursively, resulting in a stack overflow.

Change History (7)

comment:1 by jeff, 4 years ago

From the history, it seems the bug in nullary_function has been there for a couple of years. A simple way to fix is to add another overload

      nullary_function(nullary_function& other) BOOST_NOEXCEPT :
      impl(other.impl)
      {
      }

Or to add enable_if to

      template<typename F, typename = typename boost::enable_if<!boost::is_same<typename decay<F>::type, this_type>::value>::type>
      nullary_function(BOOST_THREAD_RV_REF(F) f):
      impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
      {}

in reply to:  1 comment:2 by jeff, 4 years ago

Fix a typo in the second code block: it should be enable_if_c instead of enable_if. also this_type is nullary_function<void()> or nullary_function<R()> (depending on the specialization).

      using this_type = nullary_function<void()>; 
      template<typename F, typename = typename boost::enable_if_c<!boost::is_same<typename decay<F>::type, this_type>::value>::type>
      nullary_function(BOOST_THREAD_RV_REF(F) f):
      impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
      {}

comment:3 by viboes, 4 years ago

Owner: changed from Anthony Williams to viboes
Status: newassigned

Thanks for the report. I'll try to fix it soon but a PR on github would help as well.

comment:4 by viboes, 4 years ago

I've some trouble identifying where there is recursion

      template<typename F>
      nullary_function(BOOST_THREAD_RV_REF(F) f):
      impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
      {}

impl_type is not nullary_function, isn't it? Could you clarify?

comment:5 by viboes, 4 years ago

Oh, I believe I see it now.

The problem is on the open overloads

#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
      template<typename F>
      explicit nullary_function(F& f);
#endif
      template<typename F>
      nullary_function(BOOST_THREAD_RV_REF(F) f);

comment:7 by viboes, 4 years ago

Resolution: fixed
Status: assignedclosed

Please reopen if you believe the fix is not good enough.

Note: See TracTickets for help on using tickets.