Blame SOURCES/gcc10-pr94540.patch

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