public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/63840] New: std::function copy constructor deletes an uninitialized pointer if new fails
@ 2014-11-12 20:46 tavianator at gmail dot com
  2014-11-12 23:44 ` [Bug libstdc++/63840] " redi at gcc dot gnu.org
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: tavianator at gmail dot com @ 2014-11-12 20:46 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63840

            Bug ID: 63840
           Summary: std::function copy constructor deletes an
                    uninitialized pointer if new fails
           Product: gcc
           Version: 5.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: tavianator at gmail dot com

Created attachment 33953
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33953&action=edit
Reproducer

std::function's copy constructor looks like this:

  template<typename _Res, typename... _ArgTypes>
    function<_Res(_ArgTypes...)>::
    function(const function& __x)
    : _Function_base()
    {
      if (static_cast<bool>(__x))
    {
      _M_invoker = __x._M_invoker;
      _M_manager = __x._M_manager;
      __x._M_manager(_M_functor, __x._M_functor, __clone_functor);
    }
    }

_M_manager(..., __clone_functor) calls _M_clone, which looks like this when the
functor is stored on the heap:

    static void
    _M_clone(_Any_data& __dest, const _Any_data& __source, false_type)
    {
      __dest._M_access<_Functor*>() =
        new _Functor(*__source._M_access<_Functor*>());
    }

If operator new or the copy-constructor throws, __dest._M_pod_data remains
uninitialized.  Then the stack unwinds, and ~_Function_base() gets called:

    ~_Function_base()
    {
      if (_M_manager)
    _M_manager(_M_functor, _M_functor, __destroy_functor);
    }

Which ultimately calls

    static void
    _M_destroy(_Any_data& __victim, false_type)
    {
      delete __victim._M_access<_Functor*>();
    }

Which deletes _M_pod_data.  A simple fix could be:

   template<typename _Res, typename... _ArgTypes>
     function<_Res(_ArgTypes...)>::
     function(const function& __x)
     : _Function_base()
     {
       if (static_cast<bool>(__x))
     {
+      __x._M_manager(_M_functor, __x._M_functor, __clone_functor);
       _M_invoker = __x._M_invoker;
       _M_manager = __x._M_manager;
-      __x._M_manager(_M_functor, __x._M_functor, __clone_functor);
     }
     }

I have a test case attached.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/63840] std::function copy constructor deletes an uninitialized pointer if new fails
  2014-11-12 20:46 [Bug libstdc++/63840] New: std::function copy constructor deletes an uninitialized pointer if new fails tavianator at gmail dot com
@ 2014-11-12 23:44 ` redi at gcc dot gnu.org
  2014-11-13  0:08 ` redi at gcc dot gnu.org
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2014-11-12 23:44 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63840

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |ASSIGNED
   Last reconfirmed|                            |2014-11-12
           Assignee|unassigned at gcc dot gnu.org      |redi at gcc dot gnu.org
     Ever confirmed|0                           |1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/63840] std::function copy constructor deletes an uninitialized pointer if new fails
  2014-11-12 20:46 [Bug libstdc++/63840] New: std::function copy constructor deletes an uninitialized pointer if new fails tavianator at gmail dot com
  2014-11-12 23:44 ` [Bug libstdc++/63840] " redi at gcc dot gnu.org
@ 2014-11-13  0:08 ` redi at gcc dot gnu.org
  2014-12-01 13:49 ` redi at gcc dot gnu.org
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2014-11-13  0:08 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63840

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I thought this looked familiar, I already fixed the function(F) constructor for
PR 55320 but stupidly didn't check the copy constructor.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/63840] std::function copy constructor deletes an uninitialized pointer if new fails
  2014-11-12 20:46 [Bug libstdc++/63840] New: std::function copy constructor deletes an uninitialized pointer if new fails tavianator at gmail dot com
  2014-11-12 23:44 ` [Bug libstdc++/63840] " redi at gcc dot gnu.org
  2014-11-13  0:08 ` redi at gcc dot gnu.org
@ 2014-12-01 13:49 ` redi at gcc dot gnu.org
  2014-12-01 13:50 ` redi at gcc dot gnu.org
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2014-12-01 13:49 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63840

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Author: redi
Date: Mon Dec  1 13:49:20 2014
New Revision: 218215

URL: https://gcc.gnu.org/viewcvs?rev=218215&root=gcc&view=rev
Log:
    PR libstdc++/63840
    * include/std/functional (function::function(const function&)): Set
    _M_manager after operations that might throw.
    * include/tr1/functional (function::function(const function&),
    function::function(_Functor, _Useless)): Likewise.
    * testsuite/20_util/function/63840.cc: New.
    * testsuite/tr1/3_function_objects/function/63840.cc: New.

Added:
    trunk/libstdc++-v3/testsuite/20_util/function/63840.cc
    trunk/libstdc++-v3/testsuite/tr1/3_function_objects/function/63840.cc
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/std/functional
    trunk/libstdc++-v3/include/tr1/functional


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/63840] std::function copy constructor deletes an uninitialized pointer if new fails
  2014-11-12 20:46 [Bug libstdc++/63840] New: std::function copy constructor deletes an uninitialized pointer if new fails tavianator at gmail dot com
                   ` (2 preceding siblings ...)
  2014-12-01 13:49 ` redi at gcc dot gnu.org
@ 2014-12-01 13:50 ` redi at gcc dot gnu.org
  2014-12-06 20:38 ` redi at gcc dot gnu.org
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2014-12-01 13:50 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63840

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Target Milestone|---                         |4.8.4

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Fixed on trunk so far.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/63840] std::function copy constructor deletes an uninitialized pointer if new fails
  2014-11-12 20:46 [Bug libstdc++/63840] New: std::function copy constructor deletes an uninitialized pointer if new fails tavianator at gmail dot com
                   ` (3 preceding siblings ...)
  2014-12-01 13:50 ` redi at gcc dot gnu.org
@ 2014-12-06 20:38 ` redi at gcc dot gnu.org
  2014-12-06 22:24 ` redi at gcc dot gnu.org
  2014-12-06 22:26 ` redi at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2014-12-06 20:38 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63840

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Author: redi
Date: Sat Dec  6 20:37:54 2014
New Revision: 218452

URL: https://gcc.gnu.org/viewcvs?rev=218452&root=gcc&view=rev
Log:
    PR libstdc++/63840
    * include/std/functional (function::function(const function&)): Set
    _M_manager after operations that might throw.
    * include/tr1/functional (function::function(const function&),
    function::function(_Functor, _Useless)): Likewise.
    * testsuite/20_util/function/63840.cc: New.
    * testsuite/tr1/3_function_objects/function/63840.cc: New.

Added:
    branches/gcc-4_8-branch/libstdc++-v3/testsuite/20_util/function/63840.cc
   
branches/gcc-4_8-branch/libstdc++-v3/testsuite/tr1/3_function_objects/function/63840.cc
Modified:
    branches/gcc-4_8-branch/libstdc++-v3/ChangeLog
    branches/gcc-4_8-branch/libstdc++-v3/include/std/functional
    branches/gcc-4_8-branch/libstdc++-v3/include/tr1/functional


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/63840] std::function copy constructor deletes an uninitialized pointer if new fails
  2014-11-12 20:46 [Bug libstdc++/63840] New: std::function copy constructor deletes an uninitialized pointer if new fails tavianator at gmail dot com
                   ` (4 preceding siblings ...)
  2014-12-06 20:38 ` redi at gcc dot gnu.org
@ 2014-12-06 22:24 ` redi at gcc dot gnu.org
  2014-12-06 22:26 ` redi at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2014-12-06 22:24 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63840

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Author: redi
Date: Sat Dec  6 22:24:11 2014
New Revision: 218456

URL: https://gcc.gnu.org/viewcvs?rev=218456&root=gcc&view=rev
Log:
    PR libstdc++/63840
    * include/std/functional (function::function(const function&)): Set
    _M_manager after operations that might throw.
    * include/tr1/functional (function::function(const function&),
    function::functionFunctor, _Useless)): Likewise.
    * testsuite/20_util/function/63840.cc: New.
    * testsuite/tr1/3_function_objects/function/63840.cc: New.

Added:
    branches/gcc-4_9-branch/libstdc++-v3/testsuite/20_util/function/63840.cc
   
branches/gcc-4_9-branch/libstdc++-v3/testsuite/tr1/3_function_objects/function/63840.cc
Modified:
    branches/gcc-4_9-branch/libstdc++-v3/ChangeLog
    branches/gcc-4_9-branch/libstdc++-v3/include/std/functional
    branches/gcc-4_9-branch/libstdc++-v3/include/tr1/functional


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/63840] std::function copy constructor deletes an uninitialized pointer if new fails
  2014-11-12 20:46 [Bug libstdc++/63840] New: std::function copy constructor deletes an uninitialized pointer if new fails tavianator at gmail dot com
                   ` (5 preceding siblings ...)
  2014-12-06 22:24 ` redi at gcc dot gnu.org
@ 2014-12-06 22:26 ` redi at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2014-12-06 22:26 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63840

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|ASSIGNED                    |RESOLVED
         Resolution|---                         |FIXED

--- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Fixed for 4.8.4, 4.9.3 and 5.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2014-12-06 22:26 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-12 20:46 [Bug libstdc++/63840] New: std::function copy constructor deletes an uninitialized pointer if new fails tavianator at gmail dot com
2014-11-12 23:44 ` [Bug libstdc++/63840] " redi at gcc dot gnu.org
2014-11-13  0:08 ` redi at gcc dot gnu.org
2014-12-01 13:49 ` redi at gcc dot gnu.org
2014-12-01 13:50 ` redi at gcc dot gnu.org
2014-12-06 20:38 ` redi at gcc dot gnu.org
2014-12-06 22:24 ` redi at gcc dot gnu.org
2014-12-06 22:26 ` redi at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).