]> git.ipfire.org Git - thirdparty/git.git/commitdiff
dir: free allocations on parse-error paths in `read_one_dir()`
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Sun, 5 Jul 2026 08:24:23 +0000 (08:24 +0000)
committerJunio C Hamano <gitster@pobox.com>
Sun, 5 Jul 2026 16:12:10 +0000 (09:12 -0700)
Two of `read_one_dir()`'s parse-error early returns leak ud.untracked
and ud.dirs. Plug them.

The other early returns in the same function are fine: they occur after
the `xmalloc()`+`memcpy()` that copies ud into `*untracked_`, at which
point ownership is transferred to the caller.
`read_untracked_extension()` then releases everything via
`free_untracked_cache()` on failure.

Pointed out by Coverity.

Assisted-by: Claude Opus 4.6
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
dir.c

diff --git a/dir.c b/dir.c
index 32430090dcdf2625b955d6a07b76d9c3f4e4eed3..23335b9f7ae12b558aba3cbf08f438826103c911 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -3792,13 +3792,18 @@ static int read_one_dir(struct untracked_cache_dir **untracked_,
                ALLOC_ARRAY(ud.untracked, ud.untracked_nr);
 
        ud.dirs_alloc = ud.dirs_nr = decode_varint(&data);
-       if (data > end)
+       if (data > end) {
+               free(ud.untracked);
                return -1;
+       }
        ALLOC_ARRAY(ud.dirs, ud.dirs_nr);
 
        eos = memchr(data, '\0', end - data);
-       if (!eos || eos == end)
+       if (!eos || eos == end) {
+               free(ud.untracked);
+               free(ud.dirs);
                return -1;
+       }
 
        *untracked_ = untracked = xmalloc(st_add3(sizeof(*untracked), eos - data, 1));
        memcpy(untracked, &ud, sizeof(ud));