This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug libstdc++/81891] New: heap-use-after-free if inserting element in std::unordered_map(InputIt, InputIt) throws
- From: "pdziepak at quarnos dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Fri, 18 Aug 2017 14:44:03 +0000
- Subject: [Bug libstdc++/81891] New: heap-use-after-free if inserting element in std::unordered_map(InputIt, InputIt) throws
- Auto-submitted: auto-generated
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