[PATCH] Prevent __uses_alloc from holding dangling references

Jonathan Wakely jwakely@redhat.com
Thu Jul 6 11:58:00 GMT 2017


The polymorphic_allocator::construct functions create dangling
pointers to rvalues of type memory_resource* and then dereference
them, leading to undefined behaviour.

This fixes those functions to use lvalues, and then adds a deleted
overload of __use_alloc to prevent this happening again.

This means __use_alloc can't be used like:

  f( __use_alloc<T, Alloc>(c.get_allocator()) );

because get_allocator() returns an rvalue, but it's an internal-only
helper and we can just do this instead:

  auto alloc = c.get_allocator();
  f( __use_alloc<T, Alloc>(alloc) );
  

	* include/bits/uses_allocator.h (__use_alloc(const _Alloc&&)): Add
	deleted overload to prevent dangling references to rvalues.
	* include/experimental/memory_resource
	(polymorphic_allocator::construct): Do not call __use_alloc with
	rvalue arguments.

Tested powerpc64le-linux, committed to trunk.

-------------- next part --------------
commit 072946c11b40cb13f709cb31ff5ef4a998d41f96
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Jul 6 12:22:49 2017 +0100

    Prevent __uses_alloc from holding dangling references
    
    	* include/bits/uses_allocator.h (__use_alloc(const _Alloc&&)): Add
    	deleted overload to prevent dangling references to rvalues.
    	* include/experimental/memory_resource
    	(polymorphic_allocator::construct): Do not call __use_alloc with
    	rvalue arguments.

diff --git a/libstdc++-v3/include/bits/uses_allocator.h b/libstdc++-v3/include/bits/uses_allocator.h
index 89d4e43..4d60716 100644
--- a/libstdc++-v3/include/bits/uses_allocator.h
+++ b/libstdc++-v3/include/bits/uses_allocator.h
@@ -109,6 +109,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __ret._M_a = std::__addressof(__a);
       return __ret;
     }
+
+  template<typename _Tp, typename _Alloc, typename... _Args>
+    void
+    __use_alloc(const _Alloc&&) = delete;
+
 #if __cplusplus > 201402L
   template <typename _Tp, typename _Alloc>
     inline constexpr bool uses_allocator_v =
diff --git a/libstdc++-v3/include/experimental/memory_resource b/libstdc++-v3/include/experimental/memory_resource
index 653189c..99ace7a 100644
--- a/libstdc++-v3/include/experimental/memory_resource
+++ b/libstdc++-v3/include/experimental/memory_resource
@@ -168,8 +168,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template <typename _Tp1, typename... _Args> //used here
 	void construct(_Tp1* __p, _Args&&... __args)
 	{
-	  auto __use_tag = __use_alloc<_Tp1, memory_resource*,
-	       _Args...>(this->resource());
+	  memory_resource* const __resource = this->resource();
+	  auto __use_tag
+	    = __use_alloc<_Tp1, memory_resource*, _Args...>(__resource);
 	  _M_construct(__use_tag, __p, std::forward<_Args>(__args)...);
 	}
 
@@ -180,10 +181,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		       tuple<_Args1...> __x,
 		       tuple<_Args2...> __y)
 	{
+	  memory_resource* const __resource = this->resource();
 	  auto __x_use_tag =
-	    __use_alloc<_Tp1, memory_resource*, _Args1...>(this->resource());
+	    __use_alloc<_Tp1, memory_resource*, _Args1...>(__resource);
 	  auto __y_use_tag =
-	    __use_alloc<_Tp2, memory_resource*, _Args2...>(this->resource());
+	    __use_alloc<_Tp2, memory_resource*, _Args2...>(__resource);
 
 	  ::new(__p) std::pair<_Tp1, _Tp2>(piecewise_construct,
 					   _M_construct_p(__x_use_tag, __x),


More information about the Libstdc++ mailing list