[binutils-gdb] libctf: don't leak hash keys or values on value replacement

Jose E.Marchesi jemarch@sourceware.org
Thu Oct 3 16:32:00 GMT 2019


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1820745a0af0768d9dcd515b98ad038ff9f15f23

commit 1820745a0af0768d9dcd515b98ad038ff9f15f23
Author: Nick Alcock <nick.alcock@oracle.com>
Date:   Wed Jul 24 15:21:56 2019 +0100

    libctf: don't leak hash keys or values on value replacement
    
    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.
    v5: fix tabdamage.
    
    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.

Diff:
---
 libctf/ChangeLog  |  8 ++++++++
 libctf/ctf-hash.c | 18 ++++++++++++++----
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index 28be757..08a2e3a 100644
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -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
diff --git a/libctf/ctf-hash.c b/libctf/ctf-hash.c
index c6233eb..59fceed 100644
--- a/libctf/ctf-hash.c
+++ b/libctf/ctf-hash.c
@@ -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;
 }



More information about the Binutils-cvs mailing list