public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes
@ 2012-08-17 13:08 plasmahh at gmx dot net
  2012-08-17 13:17 ` [Bug libstdc++/54296] " redi at gcc dot gnu.org
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: plasmahh at gmx dot net @ 2012-08-17 13:08 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54296

             Bug #: 54296
           Summary: using the object in the map to erase element from the
                    map crashes
    Classification: Unclassified
           Product: gcc
           Version: 4.8.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: plasmahh@gmx.net


I found a crash in my program, which boils down to the following code. (Note
that this does usually not crash, but will be reported by valgrind with invalid
read after free. Also note that depending no possible internals of the bucket
hashing stuff, the value for i where it crashes might change, so you can use
the random part multiple times to figure out a new one)

#include <unordered_map>
#include <cstddef>
#include <cstdlib>
#include <cassert>
#include <ctime>
#include <iostream>

struct A
{
        int x;
};

int main ( )
{
        srand(time(0));
        std::unordered_map<int,A> map;
        map.max_load_factor(2.0);

        for (size_t i = 0; i < 50; ++i)
        {
                A a;
                a.x = i;
                map.insert({i,a});
        }

//      int i = rand() % map.size();
        int i = 47;
        std::cout << "i = " << i << "\n";

        const A& a = map[i];

        map.erase(a.x);
}
// vim: tabstop=4 shiftwidth=4 noexpandtab ft=cpp






This seems to be due to the while condition in hashtable.h:1526 accessing __k
after the _M_deallocate_node(__p) of line 1517

while (__next_bkt == __bkt && this->_M_equals(__k, __code, __next_n));

I think it is better that after the erase of the node, __k should not be
touched anymore as it migh be part of the object being erased.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Bug libstdc++/54296] using the object in the map to erase element from the map crashes
  2012-08-17 13:08 [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes plasmahh at gmx dot net
@ 2012-08-17 13:17 ` redi at gcc dot gnu.org
  2012-08-26 10:56 ` fdumont at gcc dot gnu.org
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: redi at gcc dot gnu.org @ 2012-08-17 13:17 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54296

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |fdumont at gcc dot gnu.org

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> 2012-08-17 13:17:06 UTC ---
Francois, could you take a look please?  Thanks.

It reminds me of PR 51866, it might be good to review all the code for similar
lifetime issues following deallocation or moving.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Bug libstdc++/54296] using the object in the map to erase element from the map crashes
  2012-08-17 13:08 [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes plasmahh at gmx dot net
  2012-08-17 13:17 ` [Bug libstdc++/54296] " redi at gcc dot gnu.org
@ 2012-08-26 10:56 ` fdumont at gcc dot gnu.org
  2012-08-26 12:31 ` paolo.carlini at oracle dot com
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: fdumont at gcc dot gnu.org @ 2012-08-26 10:56 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54296

--- Comment #2 from François Dumont <fdumont at gcc dot gnu.org> 2012-08-26 10:55:43 UTC ---
I will have a closer look but what I can say for the moment is that the tested
source code doesn't seem to match the latest trunk state, the line numbers
don't match. Can you have a check with latest version ?

For info, there is a check on the address of the key to avoid just what you
describe that is to say deallocate a node and keep on using the key part of it.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Bug libstdc++/54296] using the object in the map to erase element from the map crashes
  2012-08-17 13:08 [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes plasmahh at gmx dot net
  2012-08-17 13:17 ` [Bug libstdc++/54296] " redi at gcc dot gnu.org
  2012-08-26 10:56 ` fdumont at gcc dot gnu.org
@ 2012-08-26 12:31 ` paolo.carlini at oracle dot com
  2012-08-26 12:38 ` paolo.carlini at oracle dot com
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: paolo.carlini at oracle dot com @ 2012-08-26 12:31 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54296

Paolo Carlini <paolo.carlini at oracle dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2012-08-26
     Ever Confirmed|0                           |1

--- Comment #3 from Paolo Carlini <paolo.carlini at oracle dot com> 2012-08-26 12:31:10 UTC ---
I can confirm the valgrind error:

==7930== Memcheck, a memory error detector
==7930== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==7930== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==7930== Command: ./a.out
==7930== 
i = 47
==7930== Invalid read of size 4
==7930==    at 0x40344C: std::equal_to<int>::operator()(int const&, int const&)
const (in /home/paolo/Work/a.out)
==7930==    by 0x402F6D: std::__detail::_Equal_helper<int, std::pair<int const,
A>, std::__detail::_Select1st, std::equal_to<int>, unsigned long,
false>::_S_equals(std::equal_to<int> const&, std::__detail::_Select1st const&,
int const&, unsigned long, std::__detail::_Hash_node<std::pair<int const, A>,
false>*) (in /home/paolo/Work/a.out)
==7930==    by 0x4027D5: std::__detail::_Hashtable_base<int, std::pair<int
const, A>, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>,
std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash,
std::__detail::_Hashtable_traits<false, false, true> >::_M_equals(int const&,
unsigned long, std::__detail::_Hash_node<std::pair<int const, A>, false>*)
const (in /home/paolo/Work/a.out)
==7930==    by 0x401D8C: std::_Hashtable<int, std::pair<int const, A>,
std::allocator<std::pair<int const, A> >, 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> >::erase(int const&) (in
/home/paolo/Work/a.out)
==7930==    by 0x400EB6: main (in /home/paolo/Work/a.out)
==7930==  Address 0x5d6130c is 12 bytes inside a block of size 16 free'd
==7930==    at 0x4C285BC: operator delete(void*) (in
/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==7930==    by 0x402D85:
__gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<int const, A>,
false> >::deallocate(std::__detail::_Hash_node<std::pair<int const, A>,
false>*, unsigned long) (in /home/paolo/Work/a.out)
==7930==    by 0x402756: std::_Hashtable<int, std::pair<int const, A>,
std::allocator<std::pair<int const, A> >, 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_node(std::__detail::_Hash_node<std::pair<int const, A>,
false>*) (in /home/paolo/Work/a.out)
==7930==    by 0x401D29: std::_Hashtable<int, std::pair<int const, A>,
std::allocator<std::pair<int const, A> >, 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> >::erase(int const&) (in
/home/paolo/Work/a.out)
==7930==    by 0x400EB6: main (in /home/paolo/Work/a.out)
==7930== 
==7930== 
==7930== HEAP SUMMARY:
==7930==     in use at exit: 0 bytes in 0 blocks
==7930==   total heap usage: 55 allocs, 55 frees, 1,488 bytes allocated
==7930== 
==7930== All heap blocks were freed -- no leaks are possible
==7930== 
==7930== For counts of detected and suppressed errors, rerun with: -v
==7930== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Bug libstdc++/54296] using the object in the map to erase element from the map crashes
  2012-08-17 13:08 [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes plasmahh at gmx dot net
                   ` (2 preceding siblings ...)
  2012-08-26 12:31 ` paolo.carlini at oracle dot com
@ 2012-08-26 12:38 ` paolo.carlini at oracle dot com
  2012-08-26 12:41 ` paolo.carlini at oracle dot com
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: paolo.carlini at oracle dot com @ 2012-08-26 12:38 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54296

--- Comment #4 from Paolo Carlini <paolo.carlini at oracle dot com> 2012-08-26 12:37:50 UTC ---
In current mainline line # is 1496.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Bug libstdc++/54296] using the object in the map to erase element from the map crashes
  2012-08-17 13:08 [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes plasmahh at gmx dot net
                   ` (3 preceding siblings ...)
  2012-08-26 12:38 ` paolo.carlini at oracle dot com
@ 2012-08-26 12:41 ` paolo.carlini at oracle dot com
  2012-08-26 23:07 ` paolo.carlini at oracle dot com
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: paolo.carlini at oracle dot com @ 2012-08-26 12:41 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54296

Paolo Carlini <paolo.carlini at oracle dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P3                          |P2


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Bug libstdc++/54296] using the object in the map to erase element from the map crashes
  2012-08-17 13:08 [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes plasmahh at gmx dot net
                   ` (4 preceding siblings ...)
  2012-08-26 12:41 ` paolo.carlini at oracle dot com
@ 2012-08-26 23:07 ` paolo.carlini at oracle dot com
  2012-08-26 23:16 ` paolo.carlini at oracle dot com
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: paolo.carlini at oracle dot com @ 2012-08-26 23:07 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54296

--- Comment #5 from Paolo Carlini <paolo.carlini at oracle dot com> 2012-08-26 23:07:14 UTC ---
Interestingly, however, I'm seeing a *very* similar valgrind error with 4.6.2
and 4.5.4 (which had the "old" implementation).

Dennis, which is the oldest GCC version which worked fine with your code?

Because the snippet attached here, whatever it shows in terms of valgrind,
doesn't look like a regression, frankly. Maybe it's a serious issue, we should
investigate further - false alarms are possible, though - but it's something
which isn't new. Dennis, likely we need a snippet closer to the code actually
crashing for you to make further progress.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Bug libstdc++/54296] using the object in the map to erase element from the map crashes
  2012-08-17 13:08 [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes plasmahh at gmx dot net
                   ` (5 preceding siblings ...)
  2012-08-26 23:07 ` paolo.carlini at oracle dot com
@ 2012-08-26 23:16 ` paolo.carlini at oracle dot com
  2012-08-26 23:21 ` paolo.carlini at oracle dot com
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: paolo.carlini at oracle dot com @ 2012-08-26 23:16 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54296

Paolo Carlini <paolo.carlini at oracle dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P2                          |P3


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Bug libstdc++/54296] using the object in the map to erase element from the map crashes
  2012-08-17 13:08 [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes plasmahh at gmx dot net
                   ` (6 preceding siblings ...)
  2012-08-26 23:16 ` paolo.carlini at oracle dot com
@ 2012-08-26 23:21 ` paolo.carlini at oracle dot com
  2012-08-27  7:59 ` fdumont at gcc dot gnu.org
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: paolo.carlini at oracle dot com @ 2012-08-26 23:21 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54296

--- Comment #6 from Paolo Carlini <paolo.carlini at oracle dot com> 2012-08-26 23:20:25 UTC ---
And of course I concur with Francois about the weird line number: current 4.8.0
doesn't have that line of code at that line number, it looks like Dennis you
are not using 4.8.0 but something else. But more importantly we badly need a
snippet actually crashing and also it would be very useful to know which older
version worked for you.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Bug libstdc++/54296] using the object in the map to erase element from the map crashes
  2012-08-17 13:08 [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes plasmahh at gmx dot net
                   ` (7 preceding siblings ...)
  2012-08-26 23:21 ` paolo.carlini at oracle dot com
@ 2012-08-27  7:59 ` fdumont at gcc dot gnu.org
  2012-08-27  9:36 ` paolo.carlini at oracle dot com
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: fdumont at gcc dot gnu.org @ 2012-08-27  7:59 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54296

--- Comment #7 from François Dumont <fdumont at gcc dot gnu.org> 2012-08-27 07:58:49 UTC ---
I confirm that it is an old issue, it has surely always be there. I managed to
reproduce it from the testsuite. The problem is that the current code works
fine when the key instance is taken from the container keys but doesn't work
when it is extracted from the container values.

The current address check is not reliable because the passed key instance could
be anywhere within the mapped value. I am preparing a patch to separate the
loop used to find the nodes to erase from the loop used to deallocate them.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Bug libstdc++/54296] using the object in the map to erase element from the map crashes
  2012-08-17 13:08 [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes plasmahh at gmx dot net
                   ` (8 preceding siblings ...)
  2012-08-27  7:59 ` fdumont at gcc dot gnu.org
@ 2012-08-27  9:36 ` paolo.carlini at oracle dot com
  2012-09-05 19:41 ` fdumont at gcc dot gnu.org
  2012-09-07  9:34 ` paolo.carlini at oracle dot com
  11 siblings, 0 replies; 13+ messages in thread
From: paolo.carlini at oracle dot com @ 2012-08-27  9:36 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54296

--- Comment #8 from Paolo Carlini <paolo.carlini at oracle dot com> 2012-08-27 09:36:08 UTC ---
Ah, very well, thanks Francois.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Bug libstdc++/54296] using the object in the map to erase element from the map crashes
  2012-08-17 13:08 [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes plasmahh at gmx dot net
                   ` (9 preceding siblings ...)
  2012-08-27  9:36 ` paolo.carlini at oracle dot com
@ 2012-09-05 19:41 ` fdumont at gcc dot gnu.org
  2012-09-07  9:34 ` paolo.carlini at oracle dot com
  11 siblings, 0 replies; 13+ messages in thread
From: fdumont at gcc dot gnu.org @ 2012-09-05 19:41 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54296

--- Comment #9 from François Dumont <fdumont at gcc dot gnu.org> 2012-09-05 19:41:21 UTC ---
Author: fdumont
Date: Wed Sep  5 19:41:16 2012
New Revision: 190991

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=190991
Log:
2012-09-05  François Dumont  <fdumont@gcc.gnu.org>

    PR libstdc++/54296
    * include/bits/hashtable.h (_M_erase(size_type, __node_base*,
    __node_type*)): New.
    (erase(const_iterator)): Use latter.
    (_M_erase(std::true_type, const key_type&)): New, likewise.
    (_M_erase(std::false_type, const key_type&)): New. Find all nodes
    matching the key before deallocating them so that the key doesn't
    get invalidated.
    (erase(const key_type&)): Use the new member functions.
    * testsuite/23_containers/unordered_map/erase/54296.cc: New.
    * testsuite/23_containers/unordered_multimap/erase/54296.cc: New.

Added:
    trunk/libstdc++-v3/testsuite/23_containers/unordered_map/erase/54276.cc
   
trunk/libstdc++-v3/testsuite/23_containers/unordered_multimap/erase/54276.cc
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/bits/hashtable.h


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Bug libstdc++/54296] using the object in the map to erase element from the map crashes
  2012-08-17 13:08 [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes plasmahh at gmx dot net
                   ` (10 preceding siblings ...)
  2012-09-05 19:41 ` fdumont at gcc dot gnu.org
@ 2012-09-07  9:34 ` paolo.carlini at oracle dot com
  11 siblings, 0 replies; 13+ messages in thread
From: paolo.carlini at oracle dot com @ 2012-09-07  9:34 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54296

Paolo Carlini <paolo.carlini at oracle dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |FIXED
   Target Milestone|---                         |4.8.0

--- Comment #10 from Paolo Carlini <paolo.carlini at oracle dot com> 2012-09-07 09:34:30 UTC ---
Fixed.


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2012-09-07  9:34 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-17 13:08 [Bug libstdc++/54296] New: using the object in the map to erase element from the map crashes plasmahh at gmx dot net
2012-08-17 13:17 ` [Bug libstdc++/54296] " redi at gcc dot gnu.org
2012-08-26 10:56 ` fdumont at gcc dot gnu.org
2012-08-26 12:31 ` paolo.carlini at oracle dot com
2012-08-26 12:38 ` paolo.carlini at oracle dot com
2012-08-26 12:41 ` paolo.carlini at oracle dot com
2012-08-26 23:07 ` paolo.carlini at oracle dot com
2012-08-26 23:16 ` paolo.carlini at oracle dot com
2012-08-26 23:21 ` paolo.carlini at oracle dot com
2012-08-27  7:59 ` fdumont at gcc dot gnu.org
2012-08-27  9:36 ` paolo.carlini at oracle dot com
2012-09-05 19:41 ` fdumont at gcc dot gnu.org
2012-09-07  9:34 ` paolo.carlini at oracle dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).