[PATCH] Fix _Hashtable::erase(iterator, iterator) (PR libstdc++/51845)
Jakub Jelinek
jakub@redhat.com
Wed Jan 18 23:16:00 GMT 2012
Hi!
As described in the PR, if two argument erase is removing the last
element of one bucket (i.e. the one referenced in _M_buckets array
for the next bucket) and then at least one element from the
following bucket, but not all elements from that next bucket,
__is_bucket_begin is initially false and in the second for (;;) iteration,
while it is already true, __n_bkt == __bkt and thus _M_remove_bucket_begin
doesn't do anything, and following if (__n && __n_bkt != __bkt) is
false as well (1 && 0), thus nothing is changed in the _M_buckets array
and we end up referencing there a removed element. We might crash if we
read it and if we modify it, we usually corrupt malloc data structures.
Fixed thusly, if __is_bucket_begin is true, then we know __n is the first
item in its bucket and thus __prev_n should be in the _M_buckets array.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2012-01-18 Jakub Jelinek <jakub@redhat.com>
PR libstdc++/51845
* include/bits/hashtable.h
(_Hashtable<>::erase(const_iterator, const_iterator)): Also update
_M_buckets[__n_bkt] if __is_bucket_begin.
--- libstdc++-v3/include/bits/hashtable.h 2012-01-15 20:59:53.765526939 +0100
+++ libstdc++-v3/include/bits/hashtable.h 2012-01-18 19:49:39.222388730 +0100
@@ -1541,7 +1541,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__bkt = __n_bkt;
}
- if (__n && __n_bkt != __bkt)
+ if (__n && (__n_bkt != __bkt || __is_bucket_begin))
_M_buckets[__n_bkt] = __prev_n;
__prev_n->_M_nxt = __n;
return iterator(__n);
Jakub
More information about the Libstdc++
mailing list