PR libstdc++/85812 fix memory leak in std::make_exception_ptr

Message ID 20180517153423.GA13862@redhat.com
State New
Headers show
Series
  • PR libstdc++/85812 fix memory leak in std::make_exception_ptr
Related show

Commit Message

Jonathan Wakely May 17, 2018, 3:34 p.m.
As the PR points out, the constructor called in the placement new
expression can throw, in which case the allocation would be leaked.

Separating the two implementations makes it much easier to read what
the code is doing.

	PR libstdc++/85812
	* libsupc++/cxxabi_init_exception.h (__cxa_free_exception): Declare.
	* libsupc++/exception_ptr.h (make_exception_ptr) [__cpp_exceptions]:
	Refactor to separate non-throwing and throwing implementations.
	[__cpp_rtti && !_GLIBCXX_HAVE_CDTOR_CALLABI]: Deallocate the memory
	if constructing the object throws.

Tested powerpc64le-linux (and also using ASan to verify the fix).
Committed to trunk. Backports to gcc-7 and gcc-8 will follow.
commit 3d02d84556f2be22945d397ed2fb4dbff8a0788e
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu May 17 13:51:04 2018 +0100

    PR libstdc++/85812 fix memory leak in std::make_exception_ptr
    
            PR libstdc++/85812
            * libsupc++/cxxabi_init_exception.h (__cxa_free_exception): Declare.
            * libsupc++/exception_ptr.h (make_exception_ptr) [__cpp_exceptions]:
            Refactor to separate non-throwing and throwing implementations.
            [__cpp_rtti && !_GLIBCXX_HAVE_CDTOR_CALLABI]: Deallocate the memory
            if constructing the object throws.

Patch

diff --git a/libstdc++-v3/libsupc++/cxxabi_init_exception.h b/libstdc++-v3/libsupc++/cxxabi_init_exception.h
index d973a087f14..e438c1008d9 100644
--- a/libstdc++-v3/libsupc++/cxxabi_init_exception.h
+++ b/libstdc++-v3/libsupc++/cxxabi_init_exception.h
@@ -62,6 +62,9 @@  namespace __cxxabiv1
       void*
       __cxa_allocate_exception(size_t) _GLIBCXX_NOTHROW;
 
+      void
+      __cxa_free_exception(void*) _GLIBCXX_NOTHROW;
+
       // Initialize exception (this is a GNU extension)
       __cxa_refcounted_exception*
       __cxa_init_primary_exception(void *object, std::type_info *tinfo,
diff --git a/libstdc++-v3/libsupc++/exception_ptr.h b/libstdc++-v3/libsupc++/exception_ptr.h
index a927327214d..bd355ed880b 100644
--- a/libstdc++-v3/libsupc++/exception_ptr.h
+++ b/libstdc++-v3/libsupc++/exception_ptr.h
@@ -178,25 +178,31 @@  namespace std
     exception_ptr 
     make_exception_ptr(_Ex __ex) _GLIBCXX_USE_NOEXCEPT
     {
-#if __cpp_exceptions
+#if __cpp_exceptions && __cpp_rtti && !_GLIBCXX_HAVE_CDTOR_CALLABI
+      void* __e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex));
+      (void) __cxxabiv1::__cxa_init_primary_exception(
+	  __e, const_cast<std::type_info*>(&typeid(__ex)),
+	  __exception_ptr::__dest_thunk<_Ex>);
       try
 	{
-#if __cpp_rtti && !_GLIBCXX_HAVE_CDTOR_CALLABI
-          void *__e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex));
-          (void)__cxxabiv1::__cxa_init_primary_exception(
-	      __e, const_cast<std::type_info*>(&typeid(__ex)),
-	      __exception_ptr::__dest_thunk<_Ex>);
           ::new (__e) _Ex(__ex);
           return exception_ptr(__e);
-#else
+	}
+      catch(...)
+	{
+	  __cxxabiv1::__cxa_free_exception(__e);
+	  return current_exception();
+	}
+#elif __cpp_exceptions
+      try
+	{
           throw __ex;
-#endif
 	}
       catch(...)
 	{
 	  return current_exception();
 	}
-#else
+#else // no RTTI and no exceptions
       return exception_ptr();
 #endif
     }