]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR libstdc++/58358 (search_n has a Complexity violation for random access iterator)
authorMitsuru Kariya <kariya_mitsuru@hotmail.com>
Wed, 11 Sep 2013 22:24:50 +0000 (22:24 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Wed, 11 Sep 2013 22:24:50 +0000 (22:24 +0000)
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

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/stl_algo.h
libstdc++-v3/testsuite/25_algorithms/search_n/58358.cc [new file with mode: 0644]
libstdc++-v3/testsuite/25_algorithms/search_n/iterator.cc

index c6c8db1b517bc0fc22e874fe2fe3e14644286a83..6eab7c7300a780cbebd2d44888c36fc7d3d570ac 100644 (file)
@@ -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
index 9d6b466cf2ee5b008fb79a53a8d9a41af921bb65..b06211e0100948844f2704c1ed9b21ae69a9fb6e 100644 (file)
@@ -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 (file)
index 0000000..b5ae346
--- /dev/null
@@ -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;
+}
index 27cffe741167bf7aae20fabd49908f98d0c27a06..10616960dc239f9fa6e7e6851c5d6302935b3d9c 100644 (file)
 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));
          }