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

Reply via email to