mesa: Fix hash table leak
authorAntoine Labour <piman@chromium.org>
Fri, 25 May 2012 01:17:50 +0000 (18:17 -0700)
committerStéphane Marchesin <marcheu@chromium.org>
Tue, 12 Jun 2012 21:42:22 +0000 (14:42 -0700)
When a value was replaced, the new key was strdup'd and leaked.
To fix this, we modify the hash table implementation to return
whether the value was replaced and free() the (now useless)
duplicate string.

src/mesa/program/hash_table.c
src/mesa/program/hash_table.h

index dc8563a330f72af2ffeb6bb5f1153268df4c8ec5..7dabadc5058fcdca69c7ea3160ae2cad55c6ac3a 100644 (file)
@@ -149,7 +149,7 @@ hash_table_insert(struct hash_table *ht, void *data, const void *key)
     insert_at_head(& ht->buckets[bucket], & node->link);
 }
 
-void
+bool
 hash_table_replace(struct hash_table *ht, void *data, const void *key)
 {
     const unsigned hash_value = (*ht->hash)(key);
@@ -162,7 +162,7 @@ hash_table_replace(struct hash_table *ht, void *data, const void *key)
 
        if ((*ht->compare)(hn->key, key) == 0) {
          hn->data = data;
-         return;
+         return true;
        }
     }
 
@@ -172,6 +172,7 @@ hash_table_replace(struct hash_table *ht, void *data, const void *key)
     hn->key = key;
 
     insert_at_head(& ht->buckets[bucket], & hn->link);
+    return false;
 }
 
 void
index bcf65df7d89be3f397430a05ff98ab7bba3c945e..a14bf13d1bd6eb59210ed0507de5682f83e68c81 100644 (file)
@@ -114,6 +114,10 @@ extern void hash_table_insert(struct hash_table *ht, void *data,
 /**
  * Add an element to a hash table with replacement
  *
+ * \return
+ * 1 if it did replace the the value (in which case the old key is kept), 0 if
+ * it did not replace the value (in which case the new key is kept).
+ *
  * \warning
  * If \c key is already in the hash table, \c data will \b replace the most
  * recently inserted \c data (see the warning in \c hash_table_insert) for
@@ -121,7 +125,7 @@ extern void hash_table_insert(struct hash_table *ht, void *data,
  *
  * \sa hash_table_insert
  */
-extern void hash_table_replace(struct hash_table *ht, void *data,
+extern int hash_table_replace(struct hash_table *ht, void *data,
     const void *key);
 
 /**
@@ -219,6 +223,7 @@ public:
     */
    void clear()
    {
+      hash_table_call_foreach(this->ht, delete_key, NULL);
       hash_table_clear(this->ht);
    }
 
@@ -258,9 +263,12 @@ public:
        * because UINT_MAX+1 = 0.
        */
       assert(value != UINT_MAX);
-      hash_table_replace(this->ht,
-                        (void *) (intptr_t) (value + 1),
-                        strdup(key));
+      char *dup_key = strdup(key);
+      int result = hash_table_replace(this->ht,
+                                     (void *) (intptr_t) (value + 1),
+                                     dup_key);
+      if (result)
+        free(dup_key);
    }
 
 private: