[gcc r9-9387] libstdc++: Make std::copy_n work with negative sizes

Jonathan Wakely redi@gcc.gnu.org
Tue Apr 20 18:53:51 GMT 2021


https://gcc.gnu.org/g:e59253bd0ab9d35652972cbb1fe09c3ba7f5a16e

commit r9-9387-ge59253bd0ab9d35652972cbb1fe09c3ba7f5a16e
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Jun 4 13:52:21 2020 +0100

    libstdc++: Make std::copy_n work with negative sizes
    
    Since it was added in C++11, std::copy_n should do nothing given a
    negative size, but for random access iterators we add the size to the
    iterator, possibly resulting in undefined behaviour.
    
    This also fixes a bug in the random_access_iterator_wrapper helper.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/stl_algo.h (copy_n): Only call __copy_n for positive
            values.
            * testsuite/util/testsuite_iterators.h
            (random_access_iterator_wrapper::operator+=): Fix range check for
            negative values.
            * testsuite/25_algorithms/copy_n/5.cc: New test.
    
    (cherry picked from commit e1008cd1d8504775e6a5e39325e396e61b39b84c)

Diff:
---
 libstdc++-v3/include/bits/stl_algo.h              |  6 +++
 libstdc++-v3/testsuite/25_algorithms/copy_n/5.cc  | 46 +++++++++++++++++++++++
 libstdc++-v3/testsuite/util/testsuite_iterators.h |  2 +-
 3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index 0b1576be98c..b20f4566ab5 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -803,6 +803,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
 	    typename iterator_traits<_InputIterator>::value_type>)
 
+      if (__n <= 0)
+	return __result;
+
+      __glibcxx_requires_can_increment(__first, __n);
+      __glibcxx_requires_can_increment(__result, __n);
+
       return std::__copy_n(__first, __n, __result,
 			   std::__iterator_category(__first));
     }
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/5.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/5.cc
new file mode 100644
index 00000000000..cfd53cd9cfa
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/5.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+
+#include <algorithm>
+#include <testsuite_iterators.h>
+
+void
+test01()
+{
+  // Negative sizes should be a no-op
+
+  using namespace __gnu_test;
+
+  const int from[2] = { 1, 2 };
+  test_container<const int, input_iterator_wrapper> f(from);
+  int* to = nullptr;
+  std::copy_n(f.begin(), -1, to);
+
+  std::copy_n(from, -20000, to); // random access
+
+  test_container<const int, random_access_iterator_wrapper> f2(from);
+  std::copy_n(f2.end(), -1, to);
+  std::copy_n(f2.begin(), -1, to);
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h b/libstdc++-v3/testsuite/util/testsuite_iterators.h
index ac646a59cb8..72945fb601c 100644
--- a/libstdc++-v3/testsuite/util/testsuite_iterators.h
+++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h
@@ -478,7 +478,7 @@ namespace __gnu_test
 	}
       else
 	{
-	  ITERATOR_VERIFY(n <= this->ptr - this->SharedInfo->first);
+	  ITERATOR_VERIFY(-n <= this->ptr - this->SharedInfo->first);
 	  this->ptr += n;
 	}
       return *this;


More information about the Libstdc++-cvs mailing list