dir: fix off by one errors for ignored and untracked entries

In `treat_directory()` we perform some logic to handle ignored and untracked entries. When populating a directory with entries we first save the current number of ignored/untracked entries and then populate new entries at the end of our arrays that keep track of those entries. When we figure out that all entries have been ignored/are untracked we then remove this tail of entries from those vectors again. But there is an off by one error in both paths that causes us to not free the first ignored and untracked entries, respectively. Fix these off-by-one errors to plug the resulting leak. While at it, massage the code a bit to match our modern code style. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Sep 26, 2024 at 13:46 UTC 04ff8008f3a27274e53c69209362a5bbe3dc4457
4 files changed +5 -4
dir.c
+2 -4
@@ -2135,8 +2135,7 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
2135 */
2136 state = path_none;
2137 } else {
2138 - int i;
2139 - for (i = old_ignored_nr + 1; i<dir->ignored_nr; ++i)
2138 + for (int i = old_ignored_nr; i < dir->ignored_nr; i++)
2139 FREE_AND_NULL(dir->ignored[i]);
2140 dir->ignored_nr = old_ignored_nr;
2141 }
@@ -2148,8 +2147,7 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
2147 */
2148 if ((dir->flags & DIR_SHOW_IGNORED_TOO) &&
2149 !(dir->flags & DIR_KEEP_UNTRACKED_CONTENTS)) {
2151 - int i;
2152 - for (i = old_untracked_nr + 1; i<dir->nr; ++i)
2150 + for (int i = old_untracked_nr; i < dir->nr; i++)
2151 FREE_AND_NULL(dir->entries[i]);
2152 dir->nr = old_untracked_nr;
2153 }
t/t3011-common-prefixes-and-directory-traversal.sh
+1
@@ -2,6 +2,7 @@
2
3 test_description='directory traversal handling, especially with common prefixes'
4
5 +TEST_PASSES_SANITIZE_LEAK=true
6 . ./test-lib.sh
7
8 test_expect_success 'setup' '
t/t7061-wtstatus-ignore.sh
+1
@@ -2,6 +2,7 @@
2
3 test_description='git-status ignored files'
4
5 +TEST_PASSES_SANITIZE_LEAK=true
6 . ./test-lib.sh
7
8 cat >expected <<\EOF
t/t7521-ignored-mode.sh
+1
@@ -2,6 +2,7 @@
2
3 test_description='git status ignored modes'
4
5 +TEST_PASSES_SANITIZE_LEAK=true
6 . ./test-lib.sh
7
8 test_expect_success 'setup initial commit and ignore file' '