This patch fixes a bug in pointer_set.c, where removing a pointer from
a pointer set would corrupt the hash table if the pointer was involved
in any hash collisions.

Bootstrapped and passed gcc regression testsuite on x86_64-unknown-linux-gnu.

Okay for google/gcc-4_6?

  -DeLesley

gcc/Changelog.annotalysis:
2011-7-26  DeLesley Hutchins  <deles...@google.com>

        * gcc/pointer-set.c (pointer_set_delete)  bugfix for case of
hash collisions


Index: gcc/pointer-set.c
===================================================================
--- gcc/pointer-set.c   (revision 176809)
+++ gcc/pointer-set.c   (working copy)
@@ -192,19 +192,16 @@ int
 pointer_set_delete (struct pointer_set_t *pset, const void *p)
 {
   size_t n = hash1 (p, pset->n_slots, pset->log_slots);
+  size_t n2;
+  const void* ptr;

+  /* find location of p */
   while (true)
     {
       if (pset->slots[n] == p)
-        {
-          pset->slots[n] = 0;
-          --pset->n_elements;
-          return 1;
-        }
+        break;
       else if (pset->slots[n] == 0)
-        {
-          return 0;
-        }
+        return 0;
       else
         {
           ++n;
@@ -212,6 +209,29 @@ pointer_set_delete (struct pointer_set_t *pset, co
             n = 0;
         }
     }
+
+  /* Remove p from set. */
+  pset->slots[n] = 0;
+
+  /* Now we need to scan foward and re-hash every value that we encounter,
+     until we find an empty slot.
+   */
+  while (true)
+    {
+      ++n;
+      if (n >= pset->n_slots)
+        n = 0;
+      ptr = pset->slots[n];
+
+      if (ptr == 0) break;
+
+      pset->slots[n] = 0;      /* remove ptr from set. */
+      n2 = insert_aux(ptr, pset->slots, pset->n_slots, pset->log_slots);
+      pset->slots[n2] = ptr;   /* put ptr back in set. */
+    }
+
+  --pset->n_elements;
+  return 1;
 }

 /* Pass each pointer in PSET to the function in FN, together with the fixed


-- 
DeLesley Hutchins | Software Engineer | deles...@google.com | 505-206-0315

Reply via email to