Greetings, For Google b/9127283, I've committed attached patch on google/gcc-4_8 branch.
Related: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56109 This caught ~10 bugs for us. erase(end()) and pop_back() on empty vector appear to be most common. -- Paul Pluzhnikov
Index: libstdc++-v3/include/bits/stl_vector.h =================================================================== --- libstdc++-v3/include/bits/stl_vector.h (revision 206330) +++ libstdc++-v3/include/bits/stl_vector.h (working copy) @@ -1050,6 +1050,10 @@ void pop_back() { +#if __google_stl_debug_vector + if (this->empty()) + __throw_logic_error(__N("pop_back() on empty vector")); +#endif --this->_M_impl._M_finish; _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish); } @@ -1135,7 +1139,13 @@ */ void insert(iterator __position, size_type __n, const value_type& __x) - { _M_fill_insert(__position, __n, __x); } + { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("insert() at invalid position")); +#endif + _M_fill_insert(__position, __n, __x); + } /** * @brief Inserts a range into the %vector. @@ -1157,13 +1167,23 @@ void insert(iterator __position, _InputIterator __first, _InputIterator __last) - { _M_insert_dispatch(__position, __first, __last, __false_type()); } + { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("insert() at invalid position")); +#endif + _M_insert_dispatch(__position, __first, __last, __false_type()); + } #else template<typename _InputIterator> void insert(iterator __position, _InputIterator __first, _InputIterator __last) { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("insert() at invalid position")); +#endif // Check whether it's an integral type. If so, it's not an iterator. typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_insert_dispatch(__position, __first, __last, _Integral()); Index: libstdc++-v3/include/bits/stl_deque.h =================================================================== --- libstdc++-v3/include/bits/stl_deque.h (revision 206330) +++ libstdc++-v3/include/bits/stl_deque.h (working copy) @@ -1552,7 +1552,13 @@ */ void insert(iterator __position, size_type __n, const value_type& __x) - { _M_fill_insert(__position, __n, __x); } + { +#if __google_stl_debug_deque + if (__position < this->begin() || __position > this->end()) + __throw_logic_error("insert() at invalid position"); +#endif + _M_fill_insert(__position, __n, __x); + } /** * @brief Inserts a range into the %deque. @@ -1570,7 +1576,13 @@ void insert(iterator __position, _InputIterator __first, _InputIterator __last) - { _M_insert_dispatch(__position, __first, __last, __false_type()); } + { +#if __google_stl_debug_deque + if (__position < this->begin() || __position > this->end()) + __throw_logic_error("insert() at invalid position"); +#endif + _M_insert_dispatch(__position, __first, __last, __false_type()); + } #else template<typename _InputIterator> void Index: libstdc++-v3/include/bits/vector.tcc =================================================================== --- libstdc++-v3/include/bits/vector.tcc (revision 206330) +++ libstdc++-v3/include/bits/vector.tcc (working copy) @@ -107,6 +107,10 @@ vector<_Tp, _Alloc>:: insert(iterator __position, const value_type& __x) { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("insert() at invalid position")); +#endif const size_type __n = __position - begin(); if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage && __position == end()) @@ -134,6 +138,10 @@ vector<_Tp, _Alloc>:: erase(iterator __position) { +#if __google_stl_debug_vector + if (__position < this->begin() || __position >= this->end()) + __throw_out_of_range(__N("erase() at invalid position")); +#endif if (__position + 1 != end()) _GLIBCXX_MOVE3(__position + 1, end(), __position); --this->_M_impl._M_finish; @@ -146,6 +154,10 @@ vector<_Tp, _Alloc>:: erase(iterator __first, iterator __last) { +#if __google_stl_debug_vector + if (__first < this->begin() || __first > __last || __last > this->end()) + __throw_out_of_range("erase() invalid range"); +#endif if (__first != __last) { if (__last != end()) @@ -298,6 +310,10 @@ vector<_Tp, _Alloc>:: emplace(iterator __position, _Args&&... __args) { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("emplace() at invalid position")); +#endif const size_type __n = __position - begin(); if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage && __position == end()) Index: libstdc++-v3/include/bits/deque.tcc =================================================================== --- libstdc++-v3/include/bits/deque.tcc (revision 206330) +++ libstdc++-v3/include/bits/deque.tcc (working copy) @@ -193,6 +193,10 @@ deque<_Tp, _Alloc>:: erase(iterator __position) { +#if __google_stl_debug_deque + if (__position < this->begin() || __position >= this->end()) + __throw_logic_error("erase() at invalid position"); +#endif iterator __next = __position; ++__next; const difference_type __index = __position - begin(); @@ -216,6 +220,10 @@ deque<_Tp, _Alloc>:: erase(iterator __first, iterator __last) { +#if __google_stl_debug_deque + if (__first < this->begin() || __first > __last || __last > this->end()) + __throw_logic_error("erase() invalid range"); +#endif if (__first == __last) return __first; else if (__first == begin() && __last == end()) Index: libstdc++-v3/include/bits/stl_bvector.h =================================================================== --- libstdc++-v3/include/bits/stl_bvector.h (revision 206330) +++ libstdc++-v3/include/bits/stl_bvector.h (working copy) @@ -978,6 +978,10 @@ iterator insert(iterator __position, const bool& __x = bool()) { +#if __google_stl_debug_bvector + if (__position < this->begin() || __position > this->end()) + __throw_logic_error("insert() at invalid position"); +#endif const difference_type __n = __position - begin(); if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_of_storage && __position == end()) @@ -997,6 +1001,8 @@ #if __google_stl_debug_bvector if (!this->_M_is_valid()) __throw_logic_error("insert() on corrupt (dangling?) vector"); + if (__position < this->begin() || __position > this->end()) + __throw_logic_error("insert() at invalid position"); #endif _M_insert_dispatch(__position, __first, __last, __false_type()); } @@ -1009,6 +1015,8 @@ #if __google_stl_debug_bvector if (!this->_M_is_valid()) __throw_logic_error("insert() on corrupt (dangling?) vector"); + if (__position < this->begin() || __position > this->end()) + __throw_logic_error("insert() at invalid position"); #endif typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_insert_dispatch(__position, __first, __last, _Integral()); @@ -1021,6 +1029,8 @@ #if __google_stl_debug_bvector if (!this->_M_is_valid()) __throw_logic_error("insert() on corrupt (dangling?) vector"); + if (__position < this->begin() || __position > this->end()) + __throw_logic_error("insert() at invalid position"); #endif _M_fill_insert(__position, __n, __x); } @@ -1043,7 +1053,8 @@ erase(iterator __position) { #if __google_stl_debug_bvector - _M_range_check(__position - begin()); + if (__position < this->begin() || __position >= this->end()) + __throw_logic_error("erase() at invalid position"); #endif if (__position + 1 != end()) std::copy(__position + 1, end(), __position); @@ -1057,6 +1068,8 @@ #if __google_stl_debug_bvector if (!this->_M_is_valid()) __throw_logic_error("erase() on corrupt (dangling?) vector"); + if (__first < this->begin() || __first > __last || __last > this->end()) + __throw_logic_error("erase() invalid range"); #endif if (__first != __last) _M_erase_at_end(std::copy(__last, end(), __first)); Index: libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc =================================================================== --- libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc (revision 206330) +++ libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc (working copy) @@ -18,7 +18,7 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1290 } +// { dg-error "no matching" "" { target *-*-* } 1310 } #include <vector> #include <utility> Index: libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc =================================================================== --- libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc (revision 206330) +++ libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc (working copy) @@ -18,7 +18,7 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1364 } +// { dg-error "no matching" "" { target *-*-* } 1384 } #include <vector> Index: libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc =================================================================== --- libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc (revision 206330) +++ libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc (working copy) @@ -18,7 +18,7 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1405 } +// { dg-error "no matching" "" { target *-*-* } 1425 } #include <vector> Index: libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc =================================================================== --- libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc (revision 206330) +++ libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc (working copy) @@ -18,7 +18,7 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1290 } +// { dg-error "no matching" "" { target *-*-* } 1310 } #include <vector> Index: libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc =================================================================== --- libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc (revision 206330) +++ libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc (working copy) @@ -18,7 +18,7 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1666 } +// { dg-error "no matching" "" { target *-*-* } 1678 } #include <deque> #include <utility> Index: libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc =================================================================== --- libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc (revision 206330) +++ libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc (working copy) @@ -18,7 +18,7 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1733 } +// { dg-error "no matching" "" { target *-*-* } 1745 } #include <deque> Index: libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc =================================================================== --- libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc (revision 206330) +++ libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc (working copy) @@ -18,7 +18,7 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1817 } +// { dg-error "no matching" "" { target *-*-* } 1829 } #include <deque> Index: libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc =================================================================== --- libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc (revision 206330) +++ libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc (working copy) @@ -18,7 +18,7 @@ // <http://www.gnu.org/licenses/>. // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1666 } +// { dg-error "no matching" "" { target *-*-* } 1678 } #include <deque>