Patchwork [google,gcc-4_7,gcc-4_8,integration] Add bounds checks to vector<bool>

login
register
mail settings
Submitter Paul Pluzhnikov
Date May 23, 2013, 3:51 p.m.
Message ID <ye6q7gip66eq.fsf@elbrus2.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/245973/
State New
Headers show

Comments

Paul Pluzhnikov - May 23, 2013, 3:51 p.m.
Greetings,

This patch adds (relatively) cheap bounds and dangling checks to
vector<bool>, similar to the checks I added to vector<T> in r195373,
r195356, etc.

Ok for google branches (gcc-4_7, gcc-4_8, integration) ?

Thanks,

--
Diego Novillo - May 24, 2013, 6:22 p.m.
On 2013-05-23 11:51 , Paul Pluzhnikov wrote:
> Greetings,
>
> This patch adds (relatively) cheap bounds and dangling checks to
> vector<bool>, similar to the checks I added to vector<T> in r195373,
> r195356, etc.
>
> Ok for google branches (gcc-4_7, gcc-4_8, integration) ?

OK.


Diego.

Patch

Index: libstdc++-v3/include/bits/stl_bvector.h
===================================================================
--- libstdc++-v3/include/bits/stl_bvector.h	(revision 199261)
+++ libstdc++-v3/include/bits/stl_bvector.h	(working copy)
@@ -438,11 +438,31 @@ 
 #endif
 
       ~_Bvector_base()
-      { this->_M_deallocate(); }
+      {
+        this->_M_deallocate();
+#if __google_stl_debug_bvector
+        __builtin_memset(this, 0xcd, sizeof(*this));
+#endif
+      }
 
     protected:
       _Bvector_impl _M_impl;
 
+#if __google_stl_debug_bvector
+      bool _M_is_valid() const
+      {
+	return (this->_M_impl._M_start._M_p == 0
+		&& this->_M_impl._M_finish._M_p == 0
+		&& this->_M_impl._M_end_of_storage == 0)
+	  || (this->_M_impl._M_start._M_p <= this->_M_impl._M_finish._M_p
+	      && this->_M_impl._M_finish._M_p <= this->_M_impl._M_end_of_storage
+	      && (this->_M_impl._M_start._M_p < this->_M_impl._M_end_of_storage
+                  || (this->_M_impl._M_start._M_p == this->_M_impl._M_end_of_storage
+                      && this->_M_impl._M_start._M_offset == 0
+                      && this->_M_impl._M_finish._M_offset == 0)));
+      }
+#endif
+
       _Bit_type*
       _M_allocate(size_t __n)
       { return _M_impl.allocate(_S_nword(__n)); }
@@ -571,6 +591,10 @@ 
     vector&
     operator=(const vector& __x)
     {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("op=() on corrupt (dangling?) vector");
+#endif
       if (&__x == this)
 	return *this;
       if (__x.size() > capacity())
@@ -587,6 +611,10 @@ 
     vector&
     operator=(vector&& __x)
     {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("op=() on corrupt (dangling?) vector");
+#endif
       // NB: DR 1204.
       // NB: DR 675.
       this->clear();
@@ -608,12 +636,22 @@ 
     // or not the type is an integer.
     void
     assign(size_type __n, const bool& __x)
-    { _M_fill_assign(__n, __x); }
+    {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("assign on corrupt (dangling?) vector");
+#endif
+      _M_fill_assign(__n, __x);
+    }
 
     template<typename _InputIterator>
       void
       assign(_InputIterator __first, _InputIterator __last)
       {
+#if __google_stl_debug_bvector
+	if (!this->_M_is_valid())
+	  __throw_logic_error("assign() on corrupt (dangling?) vector");
+#endif
 	typedef typename std::__is_integer<_InputIterator>::__type _Integral;
 	_M_assign_dispatch(__first, __last, _Integral());
       }
@@ -626,19 +664,43 @@ 
 
     iterator
     begin() _GLIBCXX_NOEXCEPT
-    { return this->_M_impl._M_start; }
+    {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("begin() on corrupt (dangling?) vector");
+#endif
+      return this->_M_impl._M_start;
+    }
 
     const_iterator
     begin() const _GLIBCXX_NOEXCEPT
-    { return this->_M_impl._M_start; }
+    {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("begin() on corrupt (dangling?) vector");
+#endif
+      return this->_M_impl._M_start;
+    }
 
     iterator
     end() _GLIBCXX_NOEXCEPT
-    { return this->_M_impl._M_finish; }
+    {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("end() on corrupt (dangling?) vector");
+#endif
+      return this->_M_impl._M_finish;
+    }
 
     const_iterator
     end() const _GLIBCXX_NOEXCEPT
-    { return this->_M_impl._M_finish; }
+    {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("end() on corrupt (dangling?) vector");
+#endif
+      return this->_M_impl._M_finish;
+    }
 
     reverse_iterator
     rbegin() _GLIBCXX_NOEXCEPT
@@ -659,11 +721,23 @@ 
 #ifdef __GXX_EXPERIMENTAL_CXX0X__
     const_iterator
     cbegin() const noexcept
-    { return this->_M_impl._M_start; }
+    {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("cbegin() on corrupt (dangling?) vector");
+#endif
+      return this->_M_impl._M_start;
+    }
 
     const_iterator
     cend() const noexcept
-    { return this->_M_impl._M_finish; }
+    {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("cend() on corrupt (dangling?) vector");
+#endif
+      return this->_M_impl._M_finish;
+    }
 
     const_reverse_iterator
     crbegin() const noexcept
@@ -681,6 +755,10 @@ 
     size_type
     max_size() const _GLIBCXX_NOEXCEPT
     {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("max_size() on corrupt (dangling?) vector");
+#endif
       const size_type __isize =
 	__gnu_cxx::__numeric_traits<difference_type>::__max
 	- int(_S_word_bit) + 1;
@@ -701,6 +779,9 @@ 
     reference
     operator[](size_type __n)
     {
+#if __google_stl_debug_bvector
+      _M_range_check(__n);
+#endif
       return *iterator(this->_M_impl._M_start._M_p
 		       + __n / int(_S_word_bit), __n % int(_S_word_bit));
     }
@@ -708,6 +789,9 @@ 
     const_reference
     operator[](size_type __n) const
     {
+#if __google_stl_debug_bvector
+      _M_range_check(__n);
+#endif
       return *const_iterator(this->_M_impl._M_start._M_p
 			     + __n / int(_S_word_bit), __n % int(_S_word_bit));
     }
@@ -740,19 +824,39 @@ 
 
     reference
     front()
-    { return *begin(); }
+    {
+#if __google_stl_debug_bvector
+      _M_range_check(0);
+#endif
+      return *begin();
+    }
 
     const_reference
     front() const
-    { return *begin(); }
+    {
+#if __google_stl_debug_bvector
+      _M_range_check(0);
+#endif
+      return *begin();
+    }
 
     reference
     back()
-    { return *(end() - 1); }
+    {
+#if __google_stl_debug_bvector
+      _M_range_check(0);
+#endif
+      return *(end() - 1);
+    }
 
     const_reference
     back() const
-    { return *(end() - 1); }
+    {
+#if __google_stl_debug_bvector
+      _M_range_check(0);
+#endif
+      return *(end() - 1);
+    }
 
     // _GLIBCXX_RESOLVE_LIB_DEFECTS
     // DR 464. Suggestion for new member functions in standard containers.
@@ -765,6 +869,10 @@ 
     void
     push_back(bool __x)
     {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("push_back() on corrupt (dangling?) vector");
+#endif
       if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_of_storage)
         *this->_M_impl._M_finish++ = __x;
       else
@@ -774,6 +882,10 @@ 
     void
     swap(vector& __x)
     {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid() || !__x._M_is_valid())
+	__throw_logic_error("swap() on corrupt (dangling?) vector");
+#endif
       std::swap(this->_M_impl._M_start, __x._M_impl._M_start);
       std::swap(this->_M_impl._M_finish, __x._M_impl._M_finish);
       std::swap(this->_M_impl._M_end_of_storage, 
@@ -811,26 +923,50 @@ 
       insert(iterator __position,
 	     _InputIterator __first, _InputIterator __last)
       {
+#if __google_stl_debug_bvector
+	if (!this->_M_is_valid())
+	  __throw_logic_error("insert() on corrupt (dangling?) vector");
+#endif
 	typedef typename std::__is_integer<_InputIterator>::__type _Integral;
 	_M_insert_dispatch(__position, __first, __last, _Integral());
       }
 
     void
     insert(iterator __position, size_type __n, const bool& __x)
-    { _M_fill_insert(__position, __n, __x); }
+    {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("insert() on corrupt (dangling?) vector");
+#endif
+      _M_fill_insert(__position, __n, __x);
+    }
 
 #ifdef __GXX_EXPERIMENTAL_CXX0X__
     void insert(iterator __p, initializer_list<bool> __l)
-    { this->insert(__p, __l.begin(), __l.end()); }
+    {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("insert() on corrupt (dangling?) vector");
 #endif
+      this->insert(__p, __l.begin(), __l.end());
+    }
+#endif
 
     void
     pop_back()
-    { --this->_M_impl._M_finish; }
+    {
+#if __google_stl_debug_bvector
+      _M_range_check(0);
+#endif
+      --this->_M_impl._M_finish;
+    }
 
     iterator
     erase(iterator __position)
     {
+#if __google_stl_debug_bvector
+      _M_range_check(__position - begin());
+#endif
       if (__position + 1 != end())
         std::copy(__position + 1, end(), __position);
       --this->_M_impl._M_finish;
@@ -840,6 +976,10 @@ 
     iterator
     erase(iterator __first, iterator __last)
     {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("erase() on corrupt (dangling?) vector");
+#endif
       if (__first != __last)
 	_M_erase_at_end(std::copy(__last, end(), __first));
       return __first;
@@ -857,12 +997,22 @@ 
 #ifdef __GXX_EXPERIMENTAL_CXX0X__
     void
     shrink_to_fit()
-    { _M_shrink_to_fit(); }
+    {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("shrink_to_fit() on corrupt (dangling?) vector");
 #endif
+      _M_shrink_to_fit();
+    }
+#endif
 
     void
     flip() _GLIBCXX_NOEXCEPT
     {
+#if __google_stl_debug_bvector
+      if (!this->_M_is_valid())
+	__throw_logic_error("flip() on corrupt (dangling?) vector");
+#endif
       for (_Bit_type * __p = this->_M_impl._M_start._M_p;
 	   __p != this->_M_impl._M_end_of_storage; ++__p)
         *__p = ~*__p;