https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81891
Bug ID: 81891 Summary: heap-use-after-free if inserting element in std::unordered_map(InputIt, InputIt) throws Product: gcc Version: 7.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: pdziepak at quarnos dot org Target Milestone: --- GCC 7.1.1 from Fedora 26 (gcc version 7.1.1 20170622 (Red Hat 7.1.1-3) (GCC)) Reproducer: --snip-- #include <array> #include <unordered_map> struct fails_on_copy { fails_on_copy() = default; fails_on_copy(const fails_on_copy&) { throw 0; }; }; int main() { std::array<std::pair<int, fails_on_copy>, 128> range; try { std::unordered_map<int, fails_on_copy> umap(range.begin(), range.end()); } catch(...) { } } --snip-- When built with AddressSanitizer: g++ -fsanitize=address -g test.cc -o test The following error is reported: $ ./test ================================================================= ==18550==ERROR: AddressSanitizer: heap-use-after-free on address 0x619000000080 at pc 0x7f3ae4dbca1a bp 0x7ffc9cfc6fc0 sp 0x7ffc9cfc6768 WRITE of size 1096 at 0x619000000080 thread T0 #0 0x7f3ae4dbca19 (/lib64/libasan.so.4+0x5ea19) #1 0x401c62 in std::_Hashtable<int, std::pair<int const, fails_on_copy>, std::allocator<std::pair<int const, fails_on_copy> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::clear() /usr/include/c++/7/bits/hashtable.h:2039 #2 0x4019b7 in std::_Hashtable<int, std::pair<int const, fails_on_copy>, std::allocator<std::pair<int const, fails_on_copy> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::~_Hashtable() /usr/include/c++/7/bits/hashtable.h:1364 #3 0x40205b in std::_Hashtable<int, std::pair<int const, fails_on_copy>, std::allocator<std::pair<int const, fails_on_copy> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Hashtable<std::pair<int, fails_on_copy>*>(std::pair<int, fails_on_copy>*, std::pair<int, fails_on_copy>*, unsigned long, std::hash<int> const&, std::__detail::_Mod_range_hashing const&, std::__detail::_Default_ranged_hash const&, std::equal_to<int> const&, std::__detail::_Select1st const&, std::allocator<std::pair<int const, fails_on_copy> > const&) /usr/include/c++/7/bits/hashtable.h:962 #4 0x401b27 in std::_Hashtable<int, std::pair<int const, fails_on_copy>, std::allocator<std::pair<int const, fails_on_copy> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Hashtable<std::pair<int, fails_on_copy>*>(std::pair<int, fails_on_copy>*, std::pair<int, fails_on_copy>*, unsigned long, std::hash<int> const&, std::equal_to<int> const&, std::allocator<std::pair<int const, fails_on_copy> > const&) /usr/include/c++/7/bits/hashtable.h:444 #5 0x401960 in std::unordered_map<int, fails_on_copy, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, fails_on_copy> > >::unordered_map<std::pair<int, fails_on_copy>*>(std::pair<int, fails_on_copy>*, std::pair<int, fails_on_copy>*, unsigned long, std::hash<int> const&, std::equal_to<int> const&, std::allocator<std::pair<int const, fails_on_copy> > const&) /usr/include/c++/7/bits/unordered_map.h:176 #6 0x40138b in main /home/pdziepak/gcc/test.cc:15 #7 0x7f3ae40f84d9 in __libc_start_main (/lib64/libc.so.6+0x204d9) #8 0x401119 in _start (/home/pdziepak/gcc/test+0x401119) 0x619000000080 is located 0 bytes inside of 1096-byte region [0x619000000080,0x6190000004c8) freed by thread T0 here: #0 0x7f3ae4e3efd0 in operator delete(void*) (/lib64/libasan.so.4+0xe0fd0) #1 0x403cfb in __gnu_cxx::new_allocator<std::__detail::_Hash_node_base*>::deallocate(std::__detail::_Hash_node_base**, unsigned long) /usr/include/c++/7/ext/new_allocator.h:125 #2 0x403145 in std::allocator_traits<std::allocator<std::__detail::_Hash_node_base*> >::deallocate(std::allocator<std::__detail::_Hash_node_base*>&, std::__detail::_Hash_node_base**, unsigned long) /usr/include/c++/7/bits/alloc_traits.h:462 #3 0x402963 in std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<int const, fails_on_copy>, false> > >::_M_deallocate_buckets(std::__detail::_Hash_node_base**, unsigned long) /usr/include/c++/7/bits/hashtable_policy.h:2121 #4 0x40218d in std::_Hashtable<int, std::pair<int const, fails_on_copy>, std::allocator<std::pair<int const, fails_on_copy> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_deallocate_buckets(std::__detail::_Hash_node_base**, unsigned long) /usr/include/c++/7/bits/hashtable.h:363 #5 0x401d37 in std::_Hashtable<int, std::pair<int const, fails_on_copy>, std::allocator<std::pair<int const, fails_on_copy> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_deallocate_buckets() /usr/include/c++/7/bits/hashtable.h:368 #6 0x402035 in std::_Hashtable<int, std::pair<int const, fails_on_copy>, std::allocator<std::pair<int const, fails_on_copy> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Hashtable<std::pair<int, fails_on_copy>*>(std::pair<int, fails_on_copy>*, std::pair<int, fails_on_copy>*, unsigned long, std::hash<int> const&, std::__detail::_Mod_range_hashing const&, std::__detail::_Default_ranged_hash const&, std::equal_to<int> const&, std::__detail::_Select1st const&, std::allocator<std::pair<int const, fails_on_copy> > const&) /usr/include/c++/7/bits/hashtable.h:984 #7 0x401b27 in std::_Hashtable<int, std::pair<int const, fails_on_copy>, std::allocator<std::pair<int const, fails_on_copy> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Hashtable<std::pair<int, fails_on_copy>*>(std::pair<int, fails_on_copy>*, std::pair<int, fails_on_copy>*, unsigned long, std::hash<int> const&, std::equal_to<int> const&, std::allocator<std::pair<int const, fails_on_copy> > const&) /usr/include/c++/7/bits/hashtable.h:444 #8 0x401960 in std::unordered_map<int, fails_on_copy, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, fails_on_copy> > >::unordered_map<std::pair<int, fails_on_copy>*>(std::pair<int, fails_on_copy>*, std::pair<int, fails_on_copy>*, unsigned long, std::hash<int> const&, std::equal_to<int> const&, std::allocator<std::pair<int const, fails_on_copy> > const&) /usr/include/c++/7/bits/unordered_map.h:176 #9 0x40138b in main /home/pdziepak/gcc/test.cc:15 #10 0x7f3ae40f84d9 in __libc_start_main (/lib64/libc.so.6+0x204d9) previously allocated by thread T0 here: #0 0x7f3ae4e3e158 in operator new(unsigned long) (/lib64/libasan.so.4+0xe0158) #1 0x403e02 in __gnu_cxx::new_allocator<std::__detail::_Hash_node_base*>::allocate(unsigned long, void const*) /usr/include/c++/7/ext/new_allocator.h:111 #2 0x403330 in std::allocator_traits<std::allocator<std::__detail::_Hash_node_base*> >::allocate(std::allocator<std::__detail::_Hash_node_base*>&, unsigned long) /usr/include/c++/7/bits/alloc_traits.h:436 #3 0x402b74 in std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<int const, fails_on_copy>, false> > >::_M_allocate_buckets(unsigned long) /usr/include/c++/7/bits/hashtable_policy.h:2107 #4 0x40258d in std::_Hashtable<int, std::pair<int const, fails_on_copy>, std::allocator<std::pair<int const, fails_on_copy> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_allocate_buckets(unsigned long) /usr/include/c++/7/bits/hashtable.h:354 #5 0x401f54 in std::_Hashtable<int, std::pair<int const, fails_on_copy>, std::allocator<std::pair<int const, fails_on_copy> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Hashtable<std::pair<int, fails_on_copy>*>(std::pair<int, fails_on_copy>*, std::pair<int, fails_on_copy>*, unsigned long, std::hash<int> const&, std::__detail::_Mod_range_hashing const&, std::__detail::_Default_ranged_hash const&, std::equal_to<int> const&, std::__detail::_Select1st const&, std::allocator<std::pair<int const, fails_on_copy> > const&) /usr/include/c++/7/bits/hashtable.h:972 #6 0x401b27 in std::_Hashtable<int, std::pair<int const, fails_on_copy>, std::allocator<std::pair<int const, fails_on_copy> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Hashtable<std::pair<int, fails_on_copy>*>(std::pair<int, fails_on_copy>*, std::pair<int, fails_on_copy>*, unsigned long, std::hash<int> const&, std::equal_to<int> const&, std::allocator<std::pair<int const, fails_on_copy> > const&) /usr/include/c++/7/bits/hashtable.h:444 #7 0x401960 in std::unordered_map<int, fails_on_copy, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, fails_on_copy> > >::unordered_map<std::pair<int, fails_on_copy>*>(std::pair<int, fails_on_copy>*, std::pair<int, fails_on_copy>*, unsigned long, std::hash<int> const&, std::equal_to<int> const&, std::allocator<std::pair<int const, fails_on_copy> > const&) /usr/include/c++/7/bits/unordered_map.h:176 #8 0x40138b in main /home/pdziepak/gcc/test.cc:15 #9 0x7f3ae40f84d9 in __libc_start_main (/lib64/libc.so.6+0x204d9) SUMMARY: AddressSanitizer: heap-use-after-free (/lib64/libasan.so.4+0x5ea19) Shadow bytes around the buggy address: 0x0c327fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c327fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c327fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c327fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c327fff8000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c327fff8010:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c327fff8020: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c327fff8030: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c327fff8040: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c327fff8050: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c327fff8060: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==18550==ABORTING