diff mbox series

[2/2] diff: plug leaks in dirstat

Message ID 20230505211917.2746751-3-gitster@pobox.com (mailing list archive)
State Accepted
Commit 83973981eb475ce90f829f8a5bd6ea99cd3bbd8e
Headers show
Series dirstat: leakfix | expand

Commit Message

Junio C Hamano May 5, 2023, 9:19 p.m. UTC
The array of dirstat_file contained in the dirstat_dir structure is
not freed after the processing ends.  Unfortunately, the member that
points at the array, .files, is incremented as the gather_dirstat()
function recursively walks it, and this needs to be plugged by
remembering the beginning of the array before gather_dirstat() mucks
with it and freeing it after we are done.

We can mark t4047 as leak-free.  t4000, which is marked as
leak-free, now can exercise dirstat in it, which will happen next.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 diff.c                  | 17 +++++++++++------
 t/t4047-diff-dirstat.sh |  2 ++
 2 files changed, 13 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/diff.c b/diff.c
index e13d0f8b67..d52db685f7 100644
--- a/diff.c
+++ b/diff.c
@@ -2975,13 +2975,18 @@  static void conclude_dirstat(struct diff_options *options,
 			     struct dirstat_dir *dir,
 			     unsigned long changed)
 {
-	/* This can happen even with many files, if everything was renames */
-	if (!changed)
-		return;
+	struct dirstat_file *to_free = dir->files;
+
+	if (!changed) {
+		/* This can happen even with many files, if everything was renames */
+		;
+	} else {
+		/* Show all directories with more than x% of the changes */
+		QSORT(dir->files, dir->nr, dirstat_compare);
+		gather_dirstat(options, dir, changed, "", 0);
+	}
 
-	/* Show all directories with more than x% of the changes */
-	QSORT(dir->files, dir->nr, dirstat_compare);
-	gather_dirstat(options, dir, changed, "", 0);
+	free(to_free);
 }
 
 static void show_dirstat(struct diff_options *options)
diff --git a/t/t4047-diff-dirstat.sh b/t/t4047-diff-dirstat.sh
index 7fec2cb9cd..70224c3da1 100755
--- a/t/t4047-diff-dirstat.sh
+++ b/t/t4047-diff-dirstat.sh
@@ -1,6 +1,8 @@ 
 #!/bin/sh
 
 test_description='diff --dirstat tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 # set up two commits where the second commit has these files