This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix _Hashtable::erase(iterator, iterator) (PR libstdc++/51845)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]