summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
authorElijah Newren <newren@gmail.com>2020-08-18 22:58:25 (GMT)
committerJunio C Hamano <gitster@pobox.com>2020-08-19 00:17:29 (GMT)
commitdad4f23ce59339bb32ad9e1cc1682c696f7a724f (patch)
tree44a55aa6e9c91af202fecd8887a7c175f1db3aa6 /dir.c
parent2befe97201e1f3175cce557866c5822793624b5a (diff)
downloadgit-dad4f23ce59339bb32ad9e1cc1682c696f7a724f.zip
git-dad4f23ce59339bb32ad9e1cc1682c696f7a724f.tar.gz
git-dad4f23ce59339bb32ad9e1cc1682c696f7a724f.tar.bz2
dir: make clear_directory() free all relevant memory
The calling convention for the dir API is supposed to end with a call to clear_directory() to free up no longer needed memory. However, clear_directory() didn't free dir->entries or dir->ignored. I believe this was an oversight, but a number of callers noticed memory leaks and started free'ing these. Unfortunately, they did so somewhat haphazardly (sometimes freeing the entries in the arrays, and sometimes only free'ing the arrays themselves). This suggests the callers weren't trying to make sure any possible memory used might be free'd, but just the memory they noticed their usecase definitely had allocated. Fix this mess by moving all the duplicated free'ing logic into clear_directory(). End by resetting dir to a pristine state so it could be reused if desired. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/dir.c b/dir.c
index fe64be3..aa96030 100644
--- a/dir.c
+++ b/dir.c
@@ -3009,8 +3009,8 @@ int remove_path(const char *name)
}
/*
- * Frees memory within dir which was allocated for exclude lists and
- * the exclude_stack. Does not free dir itself.
+ * Frees memory within dir which was allocated, and resets fields for further
+ * use. Does not free dir itself.
*/
void clear_directory(struct dir_struct *dir)
{
@@ -3030,6 +3030,13 @@ void clear_directory(struct dir_struct *dir)
free(group->pl);
}
+ for (i = 0; i < dir->ignored_nr; i++)
+ free(dir->ignored[i]);
+ for (i = 0; i < dir->nr; i++)
+ free(dir->entries[i]);
+ free(dir->ignored);
+ free(dir->entries);
+
stk = dir->exclude_stack;
while (stk) {
struct exclude_stack *prev = stk->prev;
@@ -3037,6 +3044,8 @@ void clear_directory(struct dir_struct *dir)
stk = prev;
}
strbuf_release(&dir->basebuf);
+
+ memset(&dir, 0, sizeof(*dir));
}
struct ondisk_untracked_cache {