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.
commit 072946c11b40cb13f709cb31ff5ef4a998d41f96 Author: Jonathan Wakely <jwak...@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),