aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Alcock <nick.alcock@oracle.com>2019-07-24 15:21:56 +0100
committerNick Alcock <nick.alcock@oracle.com>2019-09-23 14:12:54 +0100
commit5f8199783433ce8f5b924c2640953b21b5d71620 (patch)
tree787d91fc8b7742f6dfa5cfa824847281cc936972
parentc37135b645c3344808641a91422bad0cb916a514 (diff)
downloadgdb-5f8199783433ce8f5b924c2640953b21b5d71620.zip
gdb-5f8199783433ce8f5b924c2640953b21b5d71620.tar.gz
gdb-5f8199783433ce8f5b924c2640953b21b5d71620.tar.bz2
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. 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.
-rw-r--r--libctf/ChangeLog8
-rw-r--r--libctf/ctf-hash.c18
2 files changed, 22 insertions, 4 deletions
diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index 42608b8..1ed1946 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..271ed3b 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;
}