This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch] libstdc++/31370


Hi,

the below is what I have for this PR: basically I took the patch provided by Matthew and commonized the checks to a single _M_check_len. The same I could do for the primary template, a nice clean-up.

I was afraid the testcase could stress too much the memory management of some machines, but apparently I have no problems running it on various x86 and x86-64 linux machines and also a few non-linux machines. Thus I mean to add it too, for now.

Paolo.

///////////////////
2007-04-02  Matthew Levine  <gcc@severeweblint.org>
	    Paolo Carlini  <pcarlini@suse.de>

	PR libstdc++/31370
	* include/bits/stl_bvector.h (vector<bool>::max_size): Fix.
	(vector<bool>::_M_check_len): Add.
	* include/bits/vector.tcc (_M_fill_insert(iterator, size_type, bool),
	_M_insert_range(iterator, _ForwardIterator, _ForwardIterator,
	std::forward_iterator_tag), _M_insert_aux(iterator, bool)): Use it.
	* testsuite/23_containers/vector/bool/modifiers/insert/31370.cc: New.
	* testsuite/23_containers/vector/bool/capacity/29134.cc: Adjust.

	* include/bits/stl_vector.h (vector<>::_M_check_len): Add.
	* include/bits/vector.tcc (_M_insert_aux(iterator, const _Tp&),
	_M_fill_insert(iterator, size_type, const value_type&),
	_M_range_insert(iterator, _ForwardIterator, _ForwardIterator,
	std::forward_iterator_tag)): Use it.
Index: include/bits/stl_vector.h
===================================================================
--- include/bits/stl_vector.h	(revision 123388)
+++ include/bits/stl_vector.h	(working copy)
@@ -911,6 +911,17 @@
       void
       _M_insert_aux(iterator __position, const value_type& __x);
 
+      // Called by the latter.
+      size_type
+      _M_check_len(size_type __n, const char* __s) const
+      {
+	if (max_size() - size() < __n)
+	  __throw_length_error(__N(__s));
+
+	const size_type __len = size() + std::max(size(), __n);
+	return (__len < size() || __len > max_size()) ? max_size() : __len;
+      }
+
       // Internal erase functions follow.
 
       // Called by erase(q1,q2), clear(), resize(), _M_fill_assign,
Index: include/bits/vector.tcc
===================================================================
--- include/bits/vector.tcc	(revision 123389)
+++ include/bits/vector.tcc	(working copy)
@@ -258,17 +258,8 @@
 	}
       else
 	{
-	  const size_type __old_size = size();
-	  if (__old_size == this->max_size())
-	    __throw_length_error(__N("vector::_M_insert_aux"));
-
-	  // When sizeof(value_type) == 1 and __old_size > size_type(-1)/2
-	  // __len overflows: if we don't notice and _M_allocate doesn't
-	  // throw we crash badly later.
-	  size_type __len = __old_size != 0 ? 2 * __old_size : 1;	  
-	  if (__len < __old_size)
-	    __len = this->max_size();
-
+	  const size_type __len =
+	    _M_check_len(size_type(1), "vector::_M_insert_aux");
 	  pointer __new_start(this->_M_allocate(__len));
 	  pointer __new_finish(__new_start);
 	  try
@@ -343,15 +334,8 @@
 	    }
 	  else
 	    {
-	      const size_type __old_size = size();
-	      if (this->max_size() - __old_size < __n)
-		__throw_length_error(__N("vector::_M_fill_insert"));
-	      
-	      // See _M_insert_aux above.
-	      size_type __len = __old_size + std::max(__old_size, __n);
-	      if (__len < __old_size)
-		__len = this->max_size();
-
+	      const size_type __len =
+		_M_check_len(__n, "vector::_M_fill_insert");
 	      pointer __new_start(this->_M_allocate(__len));
 	      pointer __new_finish(__new_start);
 	      try
@@ -447,15 +431,8 @@
 	      }
 	    else
 	      {
-		const size_type __old_size = size();
-		if (this->max_size() - __old_size < __n)
-		  __throw_length_error(__N("vector::_M_range_insert"));	
-
-		// See _M_insert_aux above.
-		size_type __len = __old_size + std::max(__old_size, __n);
-		if (__len < __old_size)
-		  __len = this->max_size();
-
+		const size_type __len =
+		  _M_check_len(__n, "vector::_M_range_insert");
 		pointer __new_start(this->_M_allocate(__len));
 		pointer __new_finish(__new_start);
 		try
@@ -512,7 +489,8 @@
 	}
       else
 	{
-	  const size_type __len = size() + std::max(size(), __n);
+	  const size_type __len = 
+	    _M_check_len(__n, "vector<bool>::_M_fill_insert");
 	  _Bit_type * __q = this->_M_allocate(__len);
 	  iterator __i = _M_copy_aligned(begin(), __position,
 					 iterator(__q, 0));
@@ -547,7 +525,8 @@
 	      }
 	    else
 	      {
-		const size_type __len = size() + std::max(size(), __n);
+		const size_type __len =
+		  _M_check_len(__n, "vector<bool>::_M_insert_range");
 		_Bit_type * __q = this->_M_allocate(__len);
 		iterator __i = _M_copy_aligned(begin(), __position,
 					       iterator(__q, 0));
@@ -577,8 +556,8 @@
 	}
       else
 	{
-	  const size_type __len = size() ? 2 * size()
-	                                 : static_cast<size_type>(_S_word_bit);
+	  const size_type __len =
+	    _M_check_len(size_type(1), "vector<bool>::_M_insert_aux");
 	  _Bit_type * __q = this->_M_allocate(__len);
 	  iterator __i = _M_copy_aligned(begin(), __position,
 					 iterator(__q, 0));
Index: include/bits/stl_bvector.h
===================================================================
--- include/bits/stl_bvector.h	(revision 123389)
+++ include/bits/stl_bvector.h	(working copy)
@@ -582,9 +582,11 @@
     size_type
     max_size() const
     {
+      const size_type __isize =
+	std::numeric_limits<difference_type>::max() - int(_S_word_bit) + 1;
       const size_type __asize = _M_get_Bit_allocator().max_size();
-      return (__asize <= size_type(-1) / int(_S_word_bit) ?
-	      __asize * int(_S_word_bit) : size_type(-1));
+      return (__asize <= __isize / int(_S_word_bit)
+	      ? __asize * int(_S_word_bit) : __isize);
     }
 
     size_type
@@ -922,6 +924,16 @@
     void
     _M_insert_aux(iterator __position, bool __x);
 
+    size_type
+    _M_check_len(size_type __n, const char* __s) const
+    {
+      if (max_size() - size() < __n)
+	__throw_length_error(__N(__s));
+
+      const size_type __len = size() + std::max(size(), __n);
+      return (__len < size() || __len > max_size()) ? max_size() : __len;
+    }
+
     void
     _M_erase_at_end(iterator __pos)
     { this->_M_impl._M_finish = __pos; }
Index: testsuite/23_containers/vector/bool/modifiers/insert/31370.cc
===================================================================
--- testsuite/23_containers/vector/bool/modifiers/insert/31370.cc	(revision 0)
+++ testsuite/23_containers/vector/bool/modifiers/insert/31370.cc	(revision 0)
@@ -0,0 +1,192 @@
+// Copyright (C) 2007 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 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without Pred 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 COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 23.2.5 class vector<bool> [lib.vector.bool]
+
+// { dg-do run { xfail *-*-darwin8.[0-4].* } }
+
+#include <vector>
+#include <stdexcept>
+#include <testsuite_hooks.h>
+
+inline void
+check_cap_ge_size(const std::vector<bool>& x)
+{
+  if (x.capacity() < x.size())
+    throw std::logic_error("");
+}
+
+inline void
+check_cap_eq_maxsize(const std::vector<bool>& x)
+{
+  if (x.capacity() != x.max_size())
+    throw std::logic_error("");
+}
+
+// libstdc++/31370
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  int myexit = 0;
+
+  try
+    {
+      std::vector<bool> x;
+      x.reserve(x.max_size());
+      check_cap_eq_maxsize(x);
+    }
+  catch(std::bad_alloc&)
+    { }
+  catch(std::exception&)
+    { ++myexit; }
+  
+  // When doubling is too big, but smaller is sufficient, the resize
+  // should do smaller and be happy.  It certainly shouldn't throw
+  // other exceptions or crash.
+  try
+    {
+      std::vector<bool> x;
+      x.resize(x.max_size() / 2 + 1, false); 
+      for(int i = 0; i < std::_S_word_bit; ++i)
+	x.push_back(false);
+      check_cap_ge_size(x);
+    }
+  catch(std::bad_alloc&)
+    { }
+  catch(std::exception&)
+    { ++myexit; }
+  
+  try
+    {
+      std::vector<bool> x;
+      x.resize(x.max_size() / 2 + 1, false); 
+      x.insert(x.end(), std::_S_word_bit, false);
+      check_cap_ge_size(x);
+    }
+  catch(std::bad_alloc&)
+    { }
+  catch(std::exception&)
+    { ++myexit; }
+  
+  try
+    {
+      std::vector<bool> x;
+      x.resize(x.max_size() / 2 + 1, false); 
+      std::vector<bool> y(std::_S_word_bit, false);
+      x.insert(x.end(), y.begin(), y.end());
+      check_cap_ge_size(x);
+    }
+  catch(std::bad_alloc&)
+    { }
+  catch(std::exception&)
+    { ++myexit; }
+
+  // These tests are currently only relevant to bool: don't get burned
+  // by the attempt to round up when near the max size.
+  try
+    {
+      std::vector<bool> x;
+      x.resize(x.max_size() - std::_S_word_bit, false); 
+      for(int i = 0; i < std::_S_word_bit; ++i)
+	x.push_back(false);
+      check_cap_ge_size(x);
+    }
+  catch(std::bad_alloc&)
+    { }
+  catch(std::exception&)
+    { ++myexit; }
+  
+  try
+    {
+      std::vector<bool> x;
+      x.resize(x.max_size() - std::_S_word_bit, false); 
+      x.insert(x.end(), std::_S_word_bit, false);
+      check_cap_ge_size(x);
+    }
+  catch(std::bad_alloc&)
+    { }
+  catch(std::exception&)
+    { ++myexit; }
+
+  try
+    {
+      std::vector<bool> x;
+      x.resize(x.max_size() - std::_S_word_bit, false); 
+      std::vector<bool> y(std::_S_word_bit, false);
+      x.insert(x.end(), y.begin(), y.end());
+      check_cap_ge_size(x);
+    }
+  catch(std::bad_alloc&)
+    { }
+  catch(std::exception&)
+    { ++myexit; }
+  
+  // Attempts to put in more than max_size() items should result in a
+  // length error.
+  try
+    {
+      std::vector<bool> x;
+      x.resize(x.max_size() - std::_S_word_bit, false); 
+      for(int i = 0; i < std::_S_word_bit + 1; ++i)
+	x.push_back(false);
+      ++myexit;
+    }
+  catch(std::bad_alloc)
+    { }
+  catch(std::length_error)
+    { }
+  catch(std::exception)
+    { ++myexit; }
+  
+  try
+    {
+      std::vector<bool> x;
+      x.resize(x.max_size() - std::_S_word_bit, false); 
+      x.insert(x.end(), std::_S_word_bit + 1, false);
+      ++myexit;
+    }
+  catch(std::bad_alloc)
+    { }
+  catch(std::length_error)
+    { }
+  catch(std::exception)
+    { ++myexit; }
+
+  try
+    {
+      std::vector<bool> x;
+      x.resize(x.max_size() - std::_S_word_bit, false); 
+      std::vector<bool> y(std::_S_word_bit + 1, false);
+      x.insert(x.end(), y.begin(), y.end());
+      ++myexit;
+    }
+  catch(std::bad_alloc)
+    { }
+  catch(std::length_error)
+    { }
+  catch(std::exception)
+    { ++myexit; }
+
+  VERIFY( !myexit );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
Index: testsuite/23_containers/vector/bool/capacity/29134.cc
===================================================================
--- testsuite/23_containers/vector/bool/capacity/29134.cc	(revision 123388)
+++ testsuite/23_containers/vector/bool/capacity/29134.cc	(working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2006 Free Software Foundation, Inc.
+// Copyright (C) 2006, 2007 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
@@ -28,7 +28,11 @@
 
   std::vector<bool> vb;
 
-  VERIFY( vb.max_size() == std::vector<bool>::size_type(-1) );
+  // Actually, vector<bool> is special, see libstdc++/31370.
+  typedef std::vector<bool>::difference_type difference_type;
+  VERIFY( vb.max_size()
+	  == (std::numeric_limits<difference_type>::max()
+	      - int(std::_S_word_bit) + 1) );
 }
 
 int main()

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]