Blame SOURCES/gcc10-pr94540.patch

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