Commit 4b47d655 by Mitsuru Kariya Committed by Paolo Carlini

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
parent 088845a5
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> 2013-09-10 Ed Smith-Rowland <3dw4rd@verizon.net>
* testsuite/28_regex/traits/wchar_t/value.cc: Change template args * testsuite/28_regex/traits/wchar_t/value.cc: Change template args
......
...@@ -385,38 +385,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -385,38 +385,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_DistanceType; _DistanceType;
_DistanceType __tailSize = __last - __first; _DistanceType __tailSize = __last - __first;
const _DistanceType __pattSize = __count; _DistanceType __remainder = __count;
if (__tailSize < __pattSize) while (__remainder <= __tailSize) // the main loop...
return __last;
const _DistanceType __skipOffset = __pattSize - 1;
_RandomAccessIter __lookAhead = __first + __skipOffset;
__tailSize -= __pattSize;
while (1) // the main loop...
{ {
// __lookAhead here is always pointing to the last element of next __first += __remainder;
// possible match. __tailSize -= __remainder;
while (!(*__lookAhead == __val)) // the skip loop... // __first here is always pointing to one past the last element of
{ // next possible match.
if (__tailSize < __pattSize) _RandomAccessIter __backTrack = __first;
return __last; // Failure while (*--__backTrack == __val)
__lookAhead += __pattSize;
__tailSize -= __pattSize;
}
_DistanceType __remainder = __skipOffset;
for (_RandomAccessIter __backTrack = __lookAhead - 1;
*__backTrack == __val; --__backTrack)
{ {
if (--__remainder == 0) if (--__remainder == 0)
return (__lookAhead - __skipOffset); // Success return (__first - __count); // Success
} }
if (__remainder > __tailSize) __remainder = __count + 1 - (__first - __backTrack);
return __last; // Failure
__lookAhead += __remainder;
__tailSize -= __remainder;
} }
return __last; // Failure
} }
// search_n // search_n
...@@ -478,38 +463,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -478,38 +463,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_DistanceType; _DistanceType;
_DistanceType __tailSize = __last - __first; _DistanceType __tailSize = __last - __first;
const _DistanceType __pattSize = __count; _DistanceType __remainder = __count;
if (__tailSize < __pattSize) while (__remainder <= __tailSize) // the main loop...
return __last;
const _DistanceType __skipOffset = __pattSize - 1;
_RandomAccessIter __lookAhead = __first + __skipOffset;
__tailSize -= __pattSize;
while (1) // the main loop...
{ {
// __lookAhead here is always pointing to the last element of next __first += __remainder;
// possible match. __tailSize -= __remainder;
while (!bool(__binary_pred(*__lookAhead, __val))) // the skip loop... // __first here is always pointing to one past the last element of
{ // next possible match.
if (__tailSize < __pattSize) _RandomAccessIter __backTrack = __first;
return __last; // Failure while (__binary_pred(*--__backTrack, __val))
__lookAhead += __pattSize;
__tailSize -= __pattSize;
}
_DistanceType __remainder = __skipOffset;
for (_RandomAccessIter __backTrack = __lookAhead - 1;
__binary_pred(*__backTrack, __val); --__backTrack)
{ {
if (--__remainder == 0) if (--__remainder == 0)
return (__lookAhead - __skipOffset); // Success return (__first - __count); // Success
} }
if (__remainder > __tailSize) __remainder = __count + 1 - (__first - __backTrack);
return __last; // Failure
__lookAhead += __remainder;
__tailSize -= __remainder;
} }
return __last; // Failure
} }
// find_end for forward iterators. // find_end for forward iterators.
......
// 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;
}
...@@ -31,9 +31,11 @@ ...@@ -31,9 +31,11 @@
int array1[11] = {0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0}; int array1[11] = {0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0};
int array2[TEST_DEPTH]; int array2[TEST_DEPTH];
int pred_count;
bool bool
pred(int i, int j) pred(int i, int j)
{ {
++pred_count;
return i == j; return i == j;
} }
...@@ -90,16 +92,22 @@ int main() ...@@ -90,16 +92,22 @@ int main()
int* t1 = search_n(forwardcon.begin(), int* t1 = search_n(forwardcon.begin(),
forwardcon.end(), j, 1).ptr; forwardcon.end(), j, 1).ptr;
pred_count = 0;
int* t2 = search_n(forwardcon.begin(), int* t2 = search_n(forwardcon.begin(),
forwardcon.end(), j, 1, pred).ptr; forwardcon.end(), j, 1, pred).ptr;
VERIFY(pred_count <= i);
int* t3 = search_n(bidircon.begin(), int* t3 = search_n(bidircon.begin(),
bidircon.end(), j, 1).ptr; bidircon.end(), j, 1).ptr;
pred_count = 0;
int* t4 = search_n(bidircon.begin(), int* t4 = search_n(bidircon.begin(),
bidircon.end(), j, 1, pred).ptr; bidircon.end(), j, 1, pred).ptr;
VERIFY(pred_count <= i);
int* t5 = search_n(randomcon.begin(), int* t5 = search_n(randomcon.begin(),
randomcon.end(), j, 1).ptr; randomcon.end(), j, 1).ptr;
pred_count = 0;
int* t6 = search_n(randomcon.begin(), int* t6 = search_n(randomcon.begin(),
randomcon.end(), j, 1, pred).ptr; randomcon.end(), j, 1, pred).ptr;
VERIFY(pred_count <= i);
VERIFY((t1 == t2) && (t2 == t3) && (t3 == t4) && VERIFY((t1 == t2) && (t2 == t3) && (t3 == t4) &&
(t4 == t5) && (t5 == t6)); (t4 == t5) && (t5 == t6));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment