]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
libctf: don't leak hash keys or values on value replacement
authorNick Alcock <nick.alcock@oracle.com>
Wed, 24 Jul 2019 14:21:56 +0000 (15:21 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Mon, 23 Sep 2019 13:12:54 +0000 (14:12 +0100)
When a ctf_dynhash_insert() finds a slot already existing, it should
call the key and value free functions on the existing key and value and
move the passed-in key into place, so that the lifetime rules for hash
keys are always the same no matter whether the key existed or not but
neither are the keys or values leaked.

New in v3.

libctf/
* ctf-hash.c (ctf_hashtab_insert): Pass in the key and value
freeing functions: if set, free the key and value if the slot
already exists.  Always reassign the key.
        (ctf_dynhash_insert): Adjust call appropriately.
        (ctf_hash_insert_type): Likewise.

libctf/ChangeLog
libctf/ctf-hash.c

index 42608b861bc2f3ceefa78b23f7933909c9dd77af..1ed1946dc2e244786559e3a50040476ef03a05a8 100644 (file)
@@ -1,3 +1,11 @@
+2019-07-30  Nick Alcock  <nick.alcock@oracle.com>
+
+       * ctf-hash.c (ctf_hashtab_insert): Pass in the key and value
+       freeing functions: if set, free the key and value if the slot
+       already exists.  Always reassign the key.
+        (ctf_dynhash_insert): Adjust call appropriately.
+        (ctf_hash_insert_type): Likewise.
+
 2019-08-03  Nick Alcock  <nick.alcock@oracle.com>
 
        * ctf-create.c (ctf_add_type): Look up and use the forwarded-to
index c6233eb67677ec35a29439ca70398ee130396b20..271ed3b38d23010f400c3830dd09246134500113 100644 (file)
@@ -152,7 +152,9 @@ ctf_hashtab_lookup (struct htab *htab, const void *key, enum insert_option inser
 }
 
 static ctf_helem_t *
-ctf_hashtab_insert (struct htab *htab, void *key, void *value)
+ctf_hashtab_insert (struct htab *htab, void *key, void *value,
+                    ctf_hash_free_fun key_free,
+                    ctf_hash_free_fun value_free)
 {
   ctf_helem_t **slot;
 
@@ -169,8 +171,15 @@ ctf_hashtab_insert (struct htab *htab, void *key, void *value)
       *slot = malloc (sizeof (ctf_helem_t));
       if (!*slot)
        return NULL;
-      (*slot)->key = key;
     }
+  else
+    {
+      if (key_free)
+          key_free ((*slot)->key);
+      if (value_free)
+          value_free ((*slot)->value);
+    }
+  (*slot)->key = key;
   (*slot)->value = value;
   return *slot;
 }
@@ -180,7 +189,8 @@ ctf_dynhash_insert (ctf_dynhash_t *hp, void *key, void *value)
 {
   ctf_helem_t *slot;
 
-  slot = ctf_hashtab_insert (hp->htab, key, value);
+  slot = ctf_hashtab_insert (hp->htab, key, value,
+                             hp->key_free, hp->value_free);
 
   if (!slot)
     return errno;
@@ -317,7 +327,7 @@ ctf_hash_insert_type (ctf_hash_t *hp, ctf_file_t *fp, uint32_t type,
     return 0;             /* Just ignore empty strings on behalf of caller.  */
 
   if (ctf_hashtab_insert ((struct htab *) hp, (char *) str,
-                         (void *) (ptrdiff_t) type) != NULL)
+                         (void *) (ptrdiff_t) type, NULL, NULL) != NULL)
     return 0;
   return errno;
 }