From 34a94897e02fda653cf0c71edc2d5df207855160 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 5 May 2023 14:19:16 -0700 Subject: diff: refactor common tail part of dirstat computation This will become useful when we plug leaks in these two functions. Signed-off-by: Junio C Hamano --- diff.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/diff.c b/diff.c index 648f6717a5..e13d0f8b67 100644 --- a/diff.c +++ b/diff.c @@ -2971,6 +2971,19 @@ static int dirstat_compare(const void *_a, const void *_b) return strcmp(a->name, b->name); } +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; + + /* Show all directories with more than x% of the changes */ + QSORT(dir->files, dir->nr, dirstat_compare); + gather_dirstat(options, dir, changed, "", 0); +} + static void show_dirstat(struct diff_options *options) { int i; @@ -3060,13 +3073,7 @@ found_damage: dir.nr++; } - /* This can happen even with many files, if everything was renames */ - if (!changed) - return; - - /* Show all directories with more than x% of the changes */ - QSORT(dir.files, dir.nr, dirstat_compare); - gather_dirstat(options, &dir, changed, "", 0); + conclude_dirstat(options, &dir, changed); } static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *options) @@ -3104,13 +3111,7 @@ static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *o dir.nr++; } - /* This can happen even with many files, if everything was renames */ - if (!changed) - return; - - /* Show all directories with more than x% of the changes */ - QSORT(dir.files, dir.nr, dirstat_compare); - gather_dirstat(options, &dir, changed, "", 0); + conclude_dirstat(options, &dir, changed); } static void free_diffstat_file(struct diffstat_file *f) -- cgit v1.2.1 From 83973981eb475ce90f829f8a5bd6ea99cd3bbd8e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 5 May 2023 14:19:17 -0700 Subject: diff: plug leaks in dirstat 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 --- diff.c | 17 +++++++++++------ t/t4047-diff-dirstat.sh | 2 ++ 2 files changed, 13 insertions(+), 6 deletions(-) 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 -- cgit v1.2.1