Skip to content

Commit 7277bf8

Browse files
committed
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.
1 parent df417a4 commit 7277bf8

File tree

1 file changed

+16
-10
lines changed

1 file changed

+16
-10
lines changed

src/attrcache.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -424,21 +424,27 @@ void git_attr_cache_flush(git_repository *repo)
424424
int git_attr_cache__insert_macro(git_repository *repo, git_attr_rule *macro)
425425
{
426426
git_attr_cache *cache = git_repository_attr_cache(repo);
427-
git_strmap *macros = cache->macros;
428-
int error;
427+
git_attr_rule *preexisting;
428+
bool locked = false;
429+
int error = 0;
429430

430431
/* TODO: generate warning log if (macro->assigns.length == 0) */
431432
if (macro->assigns.length == 0)
432-
return 0;
433+
goto out;
433434

434-
if (attr_cache_lock(cache) < 0) {
435-
git_error_set(GIT_ERROR_OS, "unable to get attr cache lock");
436-
error = -1;
437-
} else {
438-
error = git_strmap_set(macros, macro->match.pattern, macro);
439-
git_mutex_unlock(&cache->lock);
440-
}
435+
if ((error = attr_cache_lock(cache)) < 0)
436+
goto out;
437+
locked = true;
438+
439+
if ((preexisting = git_strmap_get(cache->macros, macro->match.pattern)) != NULL)
440+
git_attr_rule__free(preexisting);
441441

442+
if ((error = git_strmap_set(cache->macros, macro->match.pattern, macro)) < 0)
443+
goto out;
444+
445+
out:
446+
if (locked)
447+
attr_cache_unlock(cache);
442448
return error;
443449
}
444450

0 commit comments

Comments
 (0)