re PR libstdc++/49060 (use of deleted memory in __gnu_cxx::hashtable::erase)
authorIan Lance Taylor <iant@google.com>
Wed, 25 May 2011 23:09:14 +0000 (23:09 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Wed, 25 May 2011 23:09:14 +0000 (23:09 +0000)
PR libstdc++/49060
* include/backward/hashtable.h (hashtable::erase): Don't crash if
erasing first and another element with a reference to the other
element.
* testsuite/backward/hash_set/49060.cc: New.

From-SVN: r174240

libstdc++-v3/ChangeLog
libstdc++-v3/include/backward/hashtable.h
libstdc++-v3/testsuite/backward/hash_set/49060.cc [new file with mode: 0644]

index 7c7758e66ef9da49a1302632036294a51cd1cb2b..2f5b10365b5c355057837e9a213b1f76abe6c41f 100644 (file)
@@ -1,3 +1,11 @@
+2011-05-25  Ian Lance Taylor  <iant@google.com>
+
+       PR libstdc++/49060
+       * include/backward/hashtable.h (hashtable::erase): Don't crash if
+       erasing first and another element with a reference to the other
+       element.
+       * testsuite/backward/hash_set/49060.cc: New.
+
 2011-05-25  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * include/bits/random.h (random_device::min, max): Specify constexpr.
index 0bcaec4fdc23a21bc2763c0f01ad16e4b5650235..91b0c602cecdaff3e2efef705b44505c3f5bf96f 100644 (file)
@@ -898,13 +898,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                  __next = __cur->_M_next;
                }
            }
-         if (_M_equals(_M_get_key(__first->_M_val), __key))
-           {
-             _M_buckets[__n] = __first->_M_next;
-             _M_delete_node(__first);
-             ++__erased;
-             --_M_num_elements;
-           }
+         bool __delete_first = _M_equals(_M_get_key(__first->_M_val), __key);
          if (__saved_slot)
            {
              __next = __saved_slot->_M_next;
@@ -913,6 +907,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
              ++__erased;
              --_M_num_elements;
            }
+         if (__delete_first)
+           {
+             _M_buckets[__n] = __first->_M_next;
+             _M_delete_node(__first);
+             ++__erased;
+             --_M_num_elements;
+           }
        }
       return __erased;
     }
diff --git a/libstdc++-v3/testsuite/backward/hash_set/49060.cc b/libstdc++-v3/testsuite/backward/hash_set/49060.cc
new file mode 100644 (file)
index 0000000..985cfcf
--- /dev/null
@@ -0,0 +1,35 @@
+// { dg-options "-Wno-deprecated" }
+
+#include <backward/hashtable.h>
+#include <utility>
+
+struct modulo2_hash
+{
+  size_t operator()(int const key) const
+  {
+    return key % 2;
+  }
+};
+
+struct modulo2_eq
+{
+  bool operator()(int const left, int const right) const
+  {
+    return left % 2 == right % 2;
+  }
+};
+
+int main()
+{
+  typedef std::_Select1st<std::pair<int const, int> > extract_type;
+  typedef
+    __gnu_cxx::hashtable<std::pair<int const, int>, int, modulo2_hash,
+                        extract_type, modulo2_eq, std::allocator<int> >
+      table_type;
+  table_type table(4, modulo2_hash(), modulo2_eq(), extract_type(),
+                  std::allocator<int>());
+
+  table.insert_equal(std::make_pair(2, 1));
+  table_type::iterator it(table.insert_equal(std::make_pair(4, 2)));
+  table.erase(it->first);
+}