summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2019-07-05 13:33:05 +0200
committerPatrick Steinhardt <ps@pks.im>2019-07-12 09:26:22 +0200
commit7277bf833d3d56723feee2c415d271ab933ca439 (patch)
treec1bda41ed7434a6a4cfdd77fd1e510b3ce8b3b6d
parentdf417a4325ddcc209bd208be197faf53a21e52d7 (diff)
downloadlibgit2-7277bf833d3d56723feee2c415d271ab933ca439.tar.gz
attrcache: fix multiple memory leaks when inserting macros
The function `git_attr_cache__insert_macro` is responsible for adopting macros in the per-repo macro cache. When adding a macro that replaces an already existing macro (e.g. because of re-parsing gitattributes files), then we do not free the previous macro and thus cause a memory leak. Fix this leak by first checking if the cache already has a macro defined with the same name. If so, free it before replacing the cache entry with the new instance.
-rw-r--r--src/attrcache.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/src/attrcache.c b/src/attrcache.c
index b88bc0930..52a883065 100644
--- a/src/attrcache.c
+++ b/src/attrcache.c
@@ -424,21 +424,27 @@ void git_attr_cache_flush(git_repository *repo)
int git_attr_cache__insert_macro(git_repository *repo, git_attr_rule *macro)
{
git_attr_cache *cache = git_repository_attr_cache(repo);
- git_strmap *macros = cache->macros;
- int error;
+ git_attr_rule *preexisting;
+ bool locked = false;
+ int error = 0;
/* TODO: generate warning log if (macro->assigns.length == 0) */
if (macro->assigns.length == 0)
- return 0;
+ goto out;
- if (attr_cache_lock(cache) < 0) {
- git_error_set(GIT_ERROR_OS, "unable to get attr cache lock");
- error = -1;
- } else {
- error = git_strmap_set(macros, macro->match.pattern, macro);
- git_mutex_unlock(&cache->lock);
- }
+ if ((error = attr_cache_lock(cache)) < 0)
+ goto out;
+ locked = true;
+
+ if ((preexisting = git_strmap_get(cache->macros, macro->match.pattern)) != NULL)
+ git_attr_rule__free(preexisting);
+ if ((error = git_strmap_set(cache->macros, macro->match.pattern, macro)) < 0)
+ goto out;
+
+out:
+ if (locked)
+ attr_cache_unlock(cache);
return error;
}