dir: release untracked cache data

There are several cases where we invalidate untracked cache directory
entries where we do not free the underlying data, but reset the number
of entries. This causes us to leak memory because `free_untracked()`
will not iterate over any potential entries which we still had in the
array.

Fix this issue by freeing old entries. The leak is exposed by t7519, but
plugging it alone does not make the whole test suite pass.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Patrick Steinhardt
2024-11-05 07:17:35 +01:00
committed by Junio C Hamano
parent 1981d1eb3e
commit e4ba54d47b

8
dir.c
View File

@ -1056,6 +1056,8 @@ static void do_invalidate_gitignore(struct untracked_cache_dir *dir)
{ {
int i; int i;
dir->valid = 0; dir->valid = 0;
for (size_t i = 0; i < dir->untracked_nr; i++)
free(dir->untracked[i]);
dir->untracked_nr = 0; dir->untracked_nr = 0;
for (i = 0; i < dir->dirs_nr; i++) for (i = 0; i < dir->dirs_nr; i++)
do_invalidate_gitignore(dir->dirs[i]); do_invalidate_gitignore(dir->dirs[i]);
@ -1083,6 +1085,8 @@ static void invalidate_directory(struct untracked_cache *uc,
uc->dir_invalidated++; uc->dir_invalidated++;
dir->valid = 0; dir->valid = 0;
for (size_t i = 0; i < dir->untracked_nr; i++)
free(dir->untracked[i]);
dir->untracked_nr = 0; dir->untracked_nr = 0;
for (i = 0; i < dir->dirs_nr; i++) for (i = 0; i < dir->dirs_nr; i++)
dir->dirs[i]->recurse = 0; dir->dirs[i]->recurse = 0;
@ -3573,6 +3577,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked,
* for safety.. * for safety..
*/ */
if (!untracked->valid) { if (!untracked->valid) {
for (size_t i = 0; i < untracked->untracked_nr; i++)
free(untracked->untracked[i]);
untracked->untracked_nr = 0; untracked->untracked_nr = 0;
untracked->check_only = 0; untracked->check_only = 0;
} }
@ -3905,6 +3911,8 @@ static void invalidate_one_directory(struct untracked_cache *uc,
{ {
uc->dir_invalidated++; uc->dir_invalidated++;
ucd->valid = 0; ucd->valid = 0;
for (size_t i = 0; i < ucd->untracked_nr; i++)
free(ucd->untracked[i]);
ucd->untracked_nr = 0; ucd->untracked_nr = 0;
} }