Blame SOURCES/gcc10-pr94540.patch

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