diff options
author | Mitsuru Kariya <kariya_mitsuru@hotmail.com> | 2013-09-11 22:24:50 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2013-09-11 22:24:50 +0000 |
commit | 4b47d65500aac94a4726fa57935366dd1616c14c (patch) | |
tree | c2b99462fd063dc457a51c589c4228eef285b714 | |
parent | 088845a5f0ba6f712c80bdb9a3a3e98c11f5681f (diff) | |
download | gcc-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/ChangeLog | 9 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/stl_algo.h | 74 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/25_algorithms/search_n/58358.cc | 41 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/25_algorithms/search_n/iterator.cc | 8 |
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)); } |