summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVicent Martí <tanoku@gmail.com>2012-01-19 11:38:09 -0800
committerVicent Martí <tanoku@gmail.com>2012-01-19 11:38:09 -0800
commit881e3da012453941eb2b237d85ab5636eea21c76 (patch)
treed570020a769280e0ca6ab4e87d79604d945df0c1 /src
parentd0ec3fb8f07988779783f69ab6cf5f3431c7aa3e (diff)
parent20c50b9e16c19bbbf7cf38bb4bd3177596bce61b (diff)
downloadlibgit2-881e3da012453941eb2b237d85ab5636eea21c76.tar.gz
Merge pull request #538 from carlosmn/ref-noleak
Don't leak when deleting or removing refs
Diffstat (limited to 'src')
-rw-r--r--src/hashtable.c3
-rw-r--r--src/hashtable.h10
-rw-r--r--src/refs.c6
3 files changed, 15 insertions, 4 deletions
diff --git a/src/hashtable.c b/src/hashtable.c
index f836f166d..89c44ba9e 100644
--- a/src/hashtable.c
+++ b/src/hashtable.c
@@ -213,7 +213,7 @@ void *git_hashtable_lookup(git_hashtable *self, const void *key)
return NULL;
}
-int git_hashtable_remove(git_hashtable *self, const void *key)
+int git_hashtable_remove2(git_hashtable *self, const void *key, void **old_value)
{
int hash_id;
git_hashtable_node *node;
@@ -223,6 +223,7 @@ int git_hashtable_remove(git_hashtable *self, const void *key)
for (hash_id = 0; hash_id < GIT_HASHTABLE_HASHES; ++hash_id) {
node = node_with_hash(self, key, hash_id);
if (node->key && self->key_equal(key, node->key) == 0) {
+ *old_value = node->value;
node->key = NULL;
node->value = NULL;
self->key_count--;
diff --git a/src/hashtable.h b/src/hashtable.h
index 485b17aa6..cd458eb17 100644
--- a/src/hashtable.h
+++ b/src/hashtable.h
@@ -42,7 +42,15 @@ git_hashtable *git_hashtable_alloc(size_t min_size,
git_hash_ptr hash,
git_hash_keyeq_ptr key_eq);
void *git_hashtable_lookup(git_hashtable *h, const void *key);
-int git_hashtable_remove(git_hashtable *table, const void *key);
+int git_hashtable_remove2(git_hashtable *table, const void *key, void **old_value);
+
+GIT_INLINE(int) git_hashtable_remove(git_hashtable *table, const void *key)
+{
+ void *_unused;
+ return git_hashtable_remove2(table, key, &_unused);
+}
+
+
void git_hashtable_free(git_hashtable *h);
void git_hashtable_clear(git_hashtable *h);
int git_hashtable_merge(git_hashtable *self, git_hashtable *other);
diff --git a/src/refs.c b/src/refs.c
index 340841cc6..86e5f5dba 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -984,14 +984,16 @@ static int reference_delete(git_reference *ref)
* We need to reload the packfile, remove the reference from the
* packing list, and repack */
if (ref->flags & GIT_REF_PACKED) {
+ struct packref *packref;
/* load the existing packfile */
if ((error = packed_load(ref->owner)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to delete reference");
- if (git_hashtable_remove(ref->owner->references.packfile,
- ref->name) < GIT_SUCCESS)
+ if (git_hashtable_remove2(ref->owner->references.packfile,
+ ref->name, (void **) &packref) < GIT_SUCCESS)
return git__throw(GIT_ENOTFOUND, "Reference not found");
+ git__free (packref);
error = packed_write(ref->owner);
/* If the reference is loose, we can just remove the reference