Blame SOURCES/gcc10-pr94540.patch

689ae3
commit 632183ddcc8f3aead8b4fc63c4ab59a42ef9ad00
689ae3
Author: Jonathan Wakely <jwakely@redhat.com>
689ae3
Date:   Wed Jun 17 22:49:06 2020 +0100
689ae3
689ae3
    libstdc++: Avoid stack overflow in std::vector (PR 94540)
689ae3
    
689ae3
    The std::__uninitialized_default_n algorithm used by std::vector creates
689ae3
    an initial object as a local variable then copies that into the
689ae3
    destination range. If the object is too large for the stack this
689ae3
    crashes. We should create the first object directly into the
689ae3
    destination and then copy it from there.
689ae3
    
689ae3
    This doesn't fix the bug for C++98, because in that case the initial
689ae3
    value is created as a default argument of the vector constructor i.e. in
689ae3
    the user's code, not inside libstdc++. We can't prevent that.
689ae3
    
689ae3
            PR libstdc++/94540
689ae3
            * include/bits/stl_uninitialized.h (__uninitialized_default_1<true>):
689ae3
            Construct the first value at *__first instead of on the stack.
689ae3
            (__uninitialized_default_n_1<true>): Likewise.
689ae3
            Improve comments on several of the non-standard algorithms.
689ae3
            * testsuite/20_util/specialized_algorithms/uninitialized_default/94540.cc:
689ae3
            New test.
689ae3
            * testsuite/20_util/specialized_algorithms/uninitialized_default_n/94540.cc:
689ae3
            New test.
689ae3
            * testsuite/20_util/specialized_algorithms/uninitialized_value_construct/94540.cc:
689ae3
            New test.
689ae3
            * testsuite/20_util/specialized_algorithms/uninitialized_value_construct_n/94540.cc:
689ae3
            New test.
689ae3
            * testsuite/23_containers/vector/cons/94540.cc: New test.
689ae3
689ae3
--- libstdc++-v3/include/bits/stl_uninitialized.h
689ae3
+++ libstdc++-v3/include/bits/stl_uninitialized.h
689ae3
@@ -556,7 +556,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
689ae3
 	  typedef typename iterator_traits<_ForwardIterator>::value_type
689ae3
 	    _ValueType;
689ae3
 
689ae3
-	  std::fill(__first, __last, _ValueType());
689ae3
+	  if (__first == __last)
689ae3
+	    return;
689ae3
+
689ae3
+	  typename iterator_traits<_ForwardIterator>::value_type* __val
689ae3
+	    = std::__addressof(*__first);
689ae3
+	  std::_Construct(__val);
689ae3
+	  if (++__first != __last)
689ae3
+	    std::fill(__first, __last, *__val);
689ae3
 	}
689ae3
     };
689ae3
 
689ae3
@@ -589,16 +596,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
689ae3
         static _ForwardIterator
689ae3
         __uninit_default_n(_ForwardIterator __first, _Size __n)
689ae3
         {
689ae3
-	  typedef typename iterator_traits<_ForwardIterator>::value_type
689ae3
-	    _ValueType;
689ae3
-
689ae3
-	  return std::fill_n(__first, __n, _ValueType());
689ae3
+	  if (__n > 0)
689ae3
+	    {
689ae3
+	      typename iterator_traits<_ForwardIterator>::value_type* __val
689ae3
+		= std::__addressof(*__first);
689ae3
+	      std::_Construct(__val);
689ae3
+	      ++__first;
689ae3
+	      __first = std::fill_n(__first, __n - 1, *__val);
689ae3
+	    }
689ae3
+	  return __first;
689ae3
 	}
689ae3
     };
689ae3
 
689ae3
   // __uninitialized_default
689ae3
-  // Fills [first, last) with std::distance(first, last) default
689ae3
-  // constructed value_types(s).
689ae3
+  // Fills [first, last) with value-initialized value_types.
689ae3
   template<typename _ForwardIterator>
689ae3
     inline void
689ae3
     __uninitialized_default(_ForwardIterator __first,
689ae3
@@ -615,7 +626,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
689ae3
     }
689ae3
 
689ae3
   // __uninitialized_default_n
689ae3
-  // Fills [first, first + n) with n default constructed value_type(s).
689ae3
+  // Fills [first, first + n) with value-initialized value_types.
689ae3
   template<typename _ForwardIterator, typename _Size>
689ae3
     inline _ForwardIterator
689ae3
     __uninitialized_default_n(_ForwardIterator __first, _Size __n)
689ae3
@@ -633,8 +644,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
689ae3
 
689ae3
 
689ae3
   // __uninitialized_default_a
689ae3
-  // Fills [first, last) with std::distance(first, last) default
689ae3
-  // constructed value_types(s), constructed with the allocator alloc.
689ae3
+  // Fills [first, last) with value_types constructed by the allocator
689ae3
+  // alloc, with no arguments passed to the construct call.
689ae3
   template<typename _ForwardIterator, typename _Allocator>
689ae3
     void
689ae3
     __uninitialized_default_a(_ForwardIterator __first,
689ae3
@@ -664,8 +675,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
689ae3
 
689ae3
 
689ae3
   // __uninitialized_default_n_a
689ae3
-  // Fills [first, first + n) with n default constructed value_types(s),
689ae3
-  // constructed with the allocator alloc.
689ae3
+  // Fills [first, first + n) with value_types constructed by the allocator
689ae3
+  // alloc, with no arguments passed to the construct call.
689ae3
   template<typename _ForwardIterator, typename _Size, typename _Allocator>
689ae3
     _ForwardIterator
689ae3
     __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, 
689ae3
@@ -686,6 +697,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
689ae3
 	}
689ae3
     }
689ae3
 
689ae3
+  // __uninitialized_default_n_a specialization for std::allocator,
689ae3
+  // which ignores the allocator and value-initializes the elements.
689ae3
   template<typename _ForwardIterator, typename _Size, typename _Tp>
689ae3
     inline _ForwardIterator
689ae3
     __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, 
689ae3
@@ -757,8 +770,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
689ae3
     };
689ae3
 
689ae3
   // __uninitialized_default_novalue
689ae3
-  // Fills [first, last) with std::distance(first, last) default-initialized
689ae3
-  // value_types(s).
689ae3
+  // Fills [first, last) with default-initialized value_types.
689ae3
   template<typename _ForwardIterator>
689ae3
     inline void
689ae3
     __uninitialized_default_novalue(_ForwardIterator __first,
689ae3
@@ -772,8 +784,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
689ae3
 	__uninit_default_novalue(__first, __last);
689ae3
     }
689ae3
 
689ae3
-  // __uninitialized_default_n
689ae3
-  // Fills [first, first + n) with n default-initialized value_type(s).
689ae3
+  // __uninitialized_default_novalue_n
689ae3
+  // Fills [first, first + n) with default-initialized value_types.
689ae3
   template<typename _ForwardIterator, typename _Size>
689ae3
     inline _ForwardIterator
689ae3
     __uninitialized_default_novalue_n(_ForwardIterator __first, _Size __n)
689ae3
--- /dev/null
689ae3
+++ libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_default/94540.cc
689ae3
@@ -0,0 +1,34 @@
689ae3
+// Copyright (C) 2020 Free Software Foundation, Inc.
689ae3
+//
689ae3
+// This file is part of the GNU ISO C++ Library.  This library is free
689ae3
+// software; you can redistribute it and/or modify it under the
689ae3
+// terms of the GNU General Public License as published by the
689ae3
+// Free Software Foundation; either version 3, or (at your option)
689ae3
+// any later version.
689ae3
+
689ae3
+// This library is distributed in the hope that it will be useful,
689ae3
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
689ae3
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
689ae3
+// GNU General Public License for more details.
689ae3
+
689ae3
+// You should have received a copy of the GNU General Public License along
689ae3
+// with this library; see the file COPYING3.  If not see
689ae3
+// <http://www.gnu.org/licenses/>.
689ae3
+
689ae3
+// { dg-do run { target { c++11 && { ! simulator } } } }
689ae3
+
689ae3
+#include <memory>
689ae3
+#include <testsuite_hooks.h>
689ae3
+
689ae3
+// Assume that 9MB is larger than the stack limit.
689ae3
+struct X { char data[9*1024*1024]; };
689ae3
+
689ae3
+static_assert( std::is_trivial<X>::value, "" );
689ae3
+
689ae3
+int main()
689ae3
+{
689ae3
+  auto mem = new char[sizeof(X) * 2];
689ae3
+  auto p = reinterpret_cast<X*>(mem);
689ae3
+  std::__uninitialized_default(p, p + 2);
689ae3
+  delete[] mem;
689ae3
+}
689ae3
--- /dev/null
689ae3
+++ libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_default_n/94540.cc
689ae3
@@ -0,0 +1,34 @@
689ae3
+// Copyright (C) 2020 Free Software Foundation, Inc.
689ae3
+//
689ae3
+// This file is part of the GNU ISO C++ Library.  This library is free
689ae3
+// software; you can redistribute it and/or modify it under the
689ae3
+// terms of the GNU General Public License as published by the
689ae3
+// Free Software Foundation; either version 3, or (at your option)
689ae3
+// any later version.
689ae3
+
689ae3
+// This library is distributed in the hope that it will be useful,
689ae3
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
689ae3
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
689ae3
+// GNU General Public License for more details.
689ae3
+
689ae3
+// You should have received a copy of the GNU General Public License along
689ae3
+// with this library; see the file COPYING3.  If not see
689ae3
+// <http://www.gnu.org/licenses/>.
689ae3
+
689ae3
+// { dg-do run { target { c++11 && { ! simulator } } } }
689ae3
+
689ae3
+#include <memory>
689ae3
+#include <testsuite_hooks.h>
689ae3
+
689ae3
+// Assume that 9MB is larger than the stack limit.
689ae3
+struct X { char data[9*1024*1024]; };
689ae3
+
689ae3
+static_assert( std::is_trivial<X>::value, "" );
689ae3
+
689ae3
+int main()
689ae3
+{
689ae3
+  auto mem = new char[sizeof(X) * 2];
689ae3
+  auto p = reinterpret_cast<X*>(mem);
689ae3
+  std::__uninitialized_default_n(p, 2);
689ae3
+  delete[] mem;
689ae3
+}
689ae3
--- /dev/null
689ae3
+++ libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_value_construct/94540.cc
689ae3
@@ -0,0 +1,35 @@
689ae3
+// Copyright (C) 2020 Free Software Foundation, Inc.
689ae3
+//
689ae3
+// This file is part of the GNU ISO C++ Library.  This library is free
689ae3
+// software; you can redistribute it and/or modify it under the
689ae3
+// terms of the GNU General Public License as published by the
689ae3
+// Free Software Foundation; either version 3, or (at your option)
689ae3
+// any later version.
689ae3
+
689ae3
+// This library is distributed in the hope that it will be useful,
689ae3
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
689ae3
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
689ae3
+// GNU General Public License for more details.
689ae3
+
689ae3
+// You should have received a copy of the GNU General Public License along
689ae3
+// with this library; see the file COPYING3.  If not see
689ae3
+// <http://www.gnu.org/licenses/>.
689ae3
+
689ae3
+// { dg-options "-std=gnu++17" }
689ae3
+// { dg-do run { target { c++17 && { ! simulator } } } }
689ae3
+
689ae3
+#include <memory>
689ae3
+#include <testsuite_hooks.h>
689ae3
+
689ae3
+// Assume that 9MB is larger than the stack limit.
689ae3
+struct X { char data[9*1024*1024]; };
689ae3
+
689ae3
+static_assert( std::is_trivial_v<X> );
689ae3
+
689ae3
+int main()
689ae3
+{
689ae3
+  auto mem = new char[sizeof(X) * 2];
689ae3
+  auto p = reinterpret_cast<X*>(mem);
689ae3
+  std::uninitialized_value_construct(p, p + 2);
689ae3
+  delete[] mem;
689ae3
+}
689ae3
--- /dev/null
689ae3
+++ libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_value_construct_n/94540.cc
689ae3
@@ -0,0 +1,34 @@
689ae3
+// Copyright (C) 2020 Free Software Foundation, Inc.
689ae3
+//
689ae3
+// This file is part of the GNU ISO C++ Library.  This library is free
689ae3
+// software; you can redistribute it and/or modify it under the
689ae3
+// terms of the GNU General Public License as published by the
689ae3
+// Free Software Foundation; either version 3, or (at your option)
689ae3
+// any later version.
689ae3
+
689ae3
+// This library is distributed in the hope that it will be useful,
689ae3
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
689ae3
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
689ae3
+// GNU General Public License for more details.
689ae3
+
689ae3
+// You should have received a copy of the GNU General Public License along
689ae3
+// with this library; see the file COPYING3.  If not see
689ae3
+// <http://www.gnu.org/licenses/>.
689ae3
+
689ae3
+// { dg-options "-std=gnu++17" }
689ae3
+// { dg-do run { target { c++17 && { ! simulator } } } }
689ae3
+
689ae3
+#include <memory>
689ae3
+#include <testsuite_hooks.h>
689ae3
+
689ae3
+// Assume that 9MB is larger than the stack limit.
689ae3
+struct X { char data[9*1024*1024]; };
689ae3
+
689ae3
+static_assert( std::is_trivial_v<X> );
689ae3
+
689ae3
+int main()
689ae3
+{
689ae3
+  auto mem = new char[sizeof(X) * 2];
689ae3
+  std::uninitialized_value_construct_n(reinterpret_cast<X*>(mem), 2);
689ae3
+  delete[] mem;
689ae3
+}
689ae3
--- /dev/null
689ae3
+++ libstdc++-v3/testsuite/23_containers/vector/cons/94540.cc
689ae3
@@ -0,0 +1,35 @@
689ae3
+// Copyright (C) 2020 Free Software Foundation, Inc.
689ae3
+//
689ae3
+// This file is part of the GNU ISO C++ Library.  This library is free
689ae3
+// software; you can redistribute it and/or modify it under the
689ae3
+// terms of the GNU General Public License as published by the
689ae3
+// Free Software Foundation; either version 3, or (at your option)
689ae3
+// any later version.
689ae3
+
689ae3
+// This library is distributed in the hope that it will be useful,
689ae3
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
689ae3
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
689ae3
+// GNU General Public License for more details.
689ae3
+
689ae3
+// You should have received a copy of the GNU General Public License along
689ae3
+// with this library; see the file COPYING3.  If not see
689ae3
+// <http://www.gnu.org/licenses/>.
689ae3
+
689ae3
+// { dg-do run { target { c++11 && { ! simulator } } } }
689ae3
+
689ae3
+#include <vector>
689ae3
+#include <testsuite_hooks.h>
689ae3
+
689ae3
+// Assume that 9MB is larger than the stack limit.
689ae3
+struct X { char data[9*1024*1024]; };
689ae3
+
689ae3
+static_assert( std::is_trivial<X>::value, "" );
689ae3
+
689ae3
+int main()
689ae3
+{
689ae3
+  std::vector<X> v(1);
689ae3
+  VERIFY( v.size() == 1 );
689ae3
+  v.clear();
689ae3
+  v.resize(2);
689ae3
+  VERIFY( v.size() == 2 );
689ae3
+}