aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitsuru Kariya <kariya_mitsuru@hotmail.com>2013-09-11 22:24:50 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2013-09-11 22:24:50 +0000
commit4b47d65500aac94a4726fa57935366dd1616c14c (patch)
treec2b99462fd063dc457a51c589c4228eef285b714
parent088845a5f0ba6f712c80bdb9a3a3e98c11f5681f (diff)
downloadgcc-4b47d65500aac94a4726fa57935366dd1616c14c.zip
gcc-4b47d65500aac94a4726fa57935366dd1616c14c.tar.gz
gcc-4b47d65500aac94a4726fa57935366dd1616c14c.tar.bz2
re PR libstdc++/58358 (search_n has a Complexity violation for random access iterator)
2013-09-11 Mitsuru Kariya <kariya_mitsuru@hotmail.com> Chris Jefferson <chris@bubblescope.net> PR libstdc++/58358 * include/bits/stl_algo.h (search_n): Fix to guarantee a number of comparisons <= number of elements in the range. * testsuite/25_algorithms/search_n/58358.cc: New. * testsuite/25_algorithms/search_n/iterator.cc: Extend. Co-Authored-By: Chris Jefferson <chris@bubblescope.net> From-SVN: r202510
-rw-r--r--libstdc++-v3/ChangeLog9
-rw-r--r--libstdc++-v3/include/bits/stl_algo.h74
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/search_n/58358.cc41
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/search_n/iterator.cc8
4 files changed, 80 insertions, 52 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index c6c8db1..6eab7c7 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,12 @@
+2013-09-11 Mitsuru Kariya <kariya_mitsuru@hotmail.com>
+ Chris Jefferson <chris@bubblescope.net>
+
+ PR libstdc++/58358
+ * include/bits/stl_algo.h (search_n): Fix to guarantee a number
+ of comparisons <= number of elements in the range.
+ * testsuite/25_algorithms/search_n/58358.cc: New.
+ * testsuite/25_algorithms/search_n/iterator.cc: Extend.
+
2013-09-10 Ed Smith-Rowland <3dw4rd@verizon.net>
* testsuite/28_regex/traits/wchar_t/value.cc: Change template args
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index 9d6b466..b06211e 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -385,38 +385,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_DistanceType;
_DistanceType __tailSize = __last - __first;
- const _DistanceType __pattSize = __count;
+ _DistanceType __remainder = __count;
- if (__tailSize < __pattSize)
- return __last;
-
- const _DistanceType __skipOffset = __pattSize - 1;
- _RandomAccessIter __lookAhead = __first + __skipOffset;
- __tailSize -= __pattSize;
-
- while (1) // the main loop...
+ while (__remainder <= __tailSize) // the main loop...
{
- // __lookAhead here is always pointing to the last element of next
- // possible match.
- while (!(*__lookAhead == __val)) // the skip loop...
- {
- if (__tailSize < __pattSize)
- return __last; // Failure
- __lookAhead += __pattSize;
- __tailSize -= __pattSize;
- }
- _DistanceType __remainder = __skipOffset;
- for (_RandomAccessIter __backTrack = __lookAhead - 1;
- *__backTrack == __val; --__backTrack)
+ __first += __remainder;
+ __tailSize -= __remainder;
+ // __first here is always pointing to one past the last element of
+ // next possible match.
+ _RandomAccessIter __backTrack = __first;
+ while (*--__backTrack == __val)
{
if (--__remainder == 0)
- return (__lookAhead - __skipOffset); // Success
+ return (__first - __count); // Success
}
- if (__remainder > __tailSize)
- return __last; // Failure
- __lookAhead += __remainder;
- __tailSize -= __remainder;
+ __remainder = __count + 1 - (__first - __backTrack);
}
+ return __last; // Failure
}
// search_n
@@ -478,38 +463,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_DistanceType;
_DistanceType __tailSize = __last - __first;
- const _DistanceType __pattSize = __count;
+ _DistanceType __remainder = __count;
- if (__tailSize < __pattSize)
- return __last;
-
- const _DistanceType __skipOffset = __pattSize - 1;
- _RandomAccessIter __lookAhead = __first + __skipOffset;
- __tailSize -= __pattSize;
-
- while (1) // the main loop...
+ while (__remainder <= __tailSize) // the main loop...
{
- // __lookAhead here is always pointing to the last element of next
- // possible match.
- while (!bool(__binary_pred(*__lookAhead, __val))) // the skip loop...
- {
- if (__tailSize < __pattSize)
- return __last; // Failure
- __lookAhead += __pattSize;
- __tailSize -= __pattSize;
- }
- _DistanceType __remainder = __skipOffset;
- for (_RandomAccessIter __backTrack = __lookAhead - 1;
- __binary_pred(*__backTrack, __val); --__backTrack)
+ __first += __remainder;
+ __tailSize -= __remainder;
+ // __first here is always pointing to one past the last element of
+ // next possible match.
+ _RandomAccessIter __backTrack = __first;
+ while (__binary_pred(*--__backTrack, __val))
{
if (--__remainder == 0)
- return (__lookAhead - __skipOffset); // Success
+ return (__first - __count); // Success
}
- if (__remainder > __tailSize)
- return __last; // Failure
- __lookAhead += __remainder;
- __tailSize -= __remainder;
+ __remainder = __count + 1 - (__first - __backTrack);
}
+ return __last; // Failure
}
// find_end for forward iterators.
diff --git a/libstdc++-v3/testsuite/25_algorithms/search_n/58358.cc b/libstdc++-v3/testsuite/25_algorithms/search_n/58358.cc
new file mode 100644
index 0000000..b5ae346
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/search_n/58358.cc
@@ -0,0 +1,41 @@
+// Copyright (C) 2013 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-options "-std=gnu++11" }
+
+// 25.1.9 [lib.alg.search]
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ std::vector<int> a{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+ int count = 0;
+ std::search_n(a.begin(), a.end(), 10, 1,
+ [&count](int t, int u) { ++count; return t == u; });
+ VERIFY( count <= 11 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/search_n/iterator.cc b/libstdc++-v3/testsuite/25_algorithms/search_n/iterator.cc
index 27cffe7..1061696 100644
--- a/libstdc++-v3/testsuite/25_algorithms/search_n/iterator.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/search_n/iterator.cc
@@ -31,9 +31,11 @@
int array1[11] = {0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0};
int array2[TEST_DEPTH];
+int pred_count;
bool
pred(int i, int j)
{
+ ++pred_count;
return i == j;
}
@@ -90,16 +92,22 @@ int main()
int* t1 = search_n(forwardcon.begin(),
forwardcon.end(), j, 1).ptr;
+ pred_count = 0;
int* t2 = search_n(forwardcon.begin(),
forwardcon.end(), j, 1, pred).ptr;
+ VERIFY(pred_count <= i);
int* t3 = search_n(bidircon.begin(),
bidircon.end(), j, 1).ptr;
+ pred_count = 0;
int* t4 = search_n(bidircon.begin(),
bidircon.end(), j, 1, pred).ptr;
+ VERIFY(pred_count <= i);
int* t5 = search_n(randomcon.begin(),
randomcon.end(), j, 1).ptr;
+ pred_count = 0;
int* t6 = search_n(randomcon.begin(),
randomcon.end(), j, 1, pred).ptr;
+ VERIFY(pred_count <= i);
VERIFY((t1 == t2) && (t2 == t3) && (t3 == t4) &&
(t4 == t5) && (t5 == t6));
}