From: Jonathan Wakely Date: Fri, 18 Aug 2017 17:46:57 +0000 (+0100) Subject: PR libstdc++/81891 fix double-free in hashtable constructor X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=676c4146f504d5252df1a3fb39bb5c4099bc0791;p=gcc.git PR libstdc++/81891 fix double-free in hashtable constructor PR libstdc++/81891 * include/bits/hashtable.h (_Hashtable(_InputIterator, _InputIterator, size_type, const _H1&, const _H2&, const _Hash&, const _Equal&, const _ExtractKey&, const allocator_type&)): Let destructor do clean up if an exception is thrown. * testsuite/23_containers/unordered_map/cons/81891.cc: New. From-SVN: r251185 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index fd9a6afbc3c..710cc9dd691 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,12 @@ +2017-08-18 Jonathan Wakely + + PR libstdc++/81891 + * include/bits/hashtable.h (_Hashtable(_InputIterator, _InputIterator, + size_type, const _H1&, const _H2&, const _Hash&, const _Equal&, + const _ExtractKey&, const allocator_type&)): Let destructor do clean + up if an exception is thrown. + * testsuite/23_containers/unordered_map/cons/81891.cc: New. + 2017-08-11 Jonathan Wakely PR libstdc++/81808 diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index bc7448bcf13..e0806dc93a1 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -973,17 +973,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_bucket_count = __bkt_count; } - __try - { - for (; __f != __l; ++__f) - this->insert(*__f); - } - __catch(...) - { - clear(); - _M_deallocate_buckets(); - __throw_exception_again; - } + for (; __f != __l; ++__f) + this->insert(*__f); } template. + +// { dg-do run { target c++11 } } + +#include +#include +#include + +struct fails_on_copy { + fails_on_copy() = default; + fails_on_copy(const fails_on_copy&) { throw 0; }; +}; + +using value_type = std::pair; + +void +test01() +{ + value_type p; + try + { + std::unordered_map umap(&p, &p + 1); + } + catch(...) + { } +} + +void +test02() +{ + using Alloc = __gnu_test::tracker_allocator; + using std::hash; + using std::equal_to; + + value_type p; + try + { + std::unordered_map, equal_to, Alloc> + umap(&p, &p + 1); + } + catch(...) + { } + + using counter = __gnu_test::tracker_allocator_counter; + VERIFY(counter::get_allocation_count() == counter::get_deallocation_count()); +} + +int +main() +{ + test01(); + test02(); +}