summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2016-08-16 11:33:16 +0000
committerredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2016-08-16 11:33:16 +0000
commit153d270f375ee4d9133195fac0c382ddc4737703 (patch)
treebef37ad2a61004e130733c3790b8c0f4d450509c
parentb50ad04e254aff4941c93f3cecbc2c19502252f8 (diff)
downloadgcc-153d270f375ee4d9133195fac0c382ddc4737703.tar.gz
PR 72847 Prevent double-free in std::vector<bool>
PR libstdc++/72847 * include/bits/stl_bvector.h (_Bvector_base::_M_deallocate): Zero pointers to start and end of storage. * testsuite/23_containers/vector/bool/72847.cc: New test. * include/bits/vector.tcc (vector<bool>::_M_reallocate): Only update _M_finish after deallocating. (vector<bool>::_M_fill_insert): Likewise. (vector<bool>::_M_insert_range): Likewise. (vector<bool>::_M_insert_aux): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@239497 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libstdc++-v3/ChangeLog12
-rw-r--r--libstdc++-v3/include/bits/stl_bvector.h2
-rw-r--r--libstdc++-v3/include/bits/vector.tcc14
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/bool/72847.cc49
4 files changed, 72 insertions, 5 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 73ddaac385d..a7689f451f5 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,15 @@
+2016-08-16 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/72847
+ * include/bits/stl_bvector.h (_Bvector_base::_M_deallocate): Zero
+ pointers to start and end of storage.
+ * testsuite/23_containers/vector/bool/72847.cc: New test.
+ * include/bits/vector.tcc (vector<bool>::_M_reallocate): Only update
+ _M_finish after deallocating.
+ (vector<bool>::_M_fill_insert): Likewise.
+ (vector<bool>::_M_insert_range): Likewise.
+ (vector<bool>::_M_insert_aux): Likewise.
+
2016-08-15 Ville Voutilainen <ville.voutilainen@gmail.com>
Implement LWG 2744 and LWG 2754.
diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h
index 629fe4dd902..b3ac63f521f 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -500,6 +500,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_Bit_alloc_traits::deallocate(_M_impl,
_M_impl._M_end_of_storage - __n,
__n);
+ _M_impl._M_start = _M_impl._M_finish = _Bit_iterator();
+ _M_impl._M_end_of_storage = _Bit_pointer();
}
}
diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc
index 9717b74a978..6926a8b91c4 100644
--- a/libstdc++-v3/include/bits/vector.tcc
+++ b/libstdc++-v3/include/bits/vector.tcc
@@ -708,9 +708,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
_Bit_pointer __q = this->_M_allocate(__n);
iterator __start(std::__addressof(*__q), 0);
- this->_M_impl._M_finish = _M_copy_aligned(begin(), end(), __start);
+ iterator __finish(_M_copy_aligned(begin(), end(), __start));
this->_M_deallocate();
this->_M_impl._M_start = __start;
+ this->_M_impl._M_finish = __finish;
this->_M_impl._M_end_of_storage = __q + _S_nword(__n);
}
@@ -736,11 +737,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
iterator __start(std::__addressof(*__q), 0);
iterator __i = _M_copy_aligned(begin(), __position, __start);
std::fill(__i, __i + difference_type(__n), __x);
- this->_M_impl._M_finish = std::copy(__position, end(),
- __i + difference_type(__n));
+ iterator __finish = std::copy(__position, end(),
+ __i + difference_type(__n));
this->_M_deallocate();
this->_M_impl._M_end_of_storage = __q + _S_nword(__len);
this->_M_impl._M_start = __start;
+ this->_M_impl._M_finish = __finish;
}
}
@@ -770,10 +772,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
iterator __start(std::__addressof(*__q), 0);
iterator __i = _M_copy_aligned(begin(), __position, __start);
__i = std::copy(__first, __last, __i);
- this->_M_impl._M_finish = std::copy(__position, end(), __i);
+ iterator __finish = std::copy(__position, end(), __i);
this->_M_deallocate();
this->_M_impl._M_end_of_storage = __q + _S_nword(__len);
this->_M_impl._M_start = __start;
+ this->_M_impl._M_finish = __finish;
}
}
}
@@ -798,10 +801,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
iterator __start(std::__addressof(*__q), 0);
iterator __i = _M_copy_aligned(begin(), __position, __start);
*__i++ = __x;
- this->_M_impl._M_finish = std::copy(__position, end(), __i);
+ iterator __finish = std::copy(__position, end(), __i);
this->_M_deallocate();
this->_M_impl._M_end_of_storage = __q + _S_nword(__len);
this->_M_impl._M_start = __start;
+ this->_M_impl._M_finish = __finish;
}
}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/72847.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/72847.cc
new file mode 100644
index 00000000000..7bd8b396efd
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/72847.cc
@@ -0,0 +1,49 @@
+// Copyright (C) 2016 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-require-cstdint "" }
+// { dg-skip-if "" { *-*-* } { "-fno-exceptions" } }
+
+#include <vector>
+#include <ext/throw_allocator.h>
+#include <testsuite_hooks.h>
+
+// PR libstdc++/72847
+void
+test01()
+{
+ bool test __attribute((unused)) = true;
+
+ typedef bool value_type;
+ typedef __gnu_cxx::throw_allocator_limit<value_type> allocator_type;
+ typedef std::vector<value_type, allocator_type> test_type;
+ test_type v1(1, false);
+ test_type v2(v1.capacity()+1, false);
+ allocator_type::set_limit(0);
+ try {
+ v1 = v2;
+ } catch (const __gnu_cxx::forced_error&) {
+ }
+ // throw_allocator will throw if double-free happens
+}
+
+// Container requirement testing, exceptional behavior
+int main()
+{
+ test01();
+ return 0;
+}