diff options
author | Patrick Steinhardt <ps@pks.im> | 2019-07-05 13:33:05 +0200 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2019-07-12 09:26:22 +0200 |
commit | 7277bf833d3d56723feee2c415d271ab933ca439 (patch) | |
tree | c1bda41ed7434a6a4cfdd77fd1e510b3ce8b3b6d | |
parent | df417a4325ddcc209bd208be197faf53a21e52d7 (diff) | |
download | libgit2-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.c | 26 |
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; } |