dir: free allocations on parse-error paths in `read_one_dir()`

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>

Johannes Schindelin committed Jul 5, 2026 at 08:24 UTC 6eb60059bd6d852d41c5e5c43bf5b033abbfca3b
1 file changed +7 -2
dir.c
+7 -2
@@ -3792,13 +3792,18 @@ static int read_one_dir(struct untracked_cache_dir **untracked_,
3792 ALLOC_ARRAY(ud.untracked, ud.untracked_nr);
3793
3794 ud.dirs_alloc = ud.dirs_nr = decode_varint(&data);
3795 - if (data > end)
3795 + if (data > end) {
3796 + free(ud.untracked);
3797 return -1;
3798 + }
3799 ALLOC_ARRAY(ud.dirs, ud.dirs_nr);
3800
3801 eos = memchr(data, '\0', end - data);
3800 - if (!eos || eos == end)
3802 + if (!eos || eos == end) {
3803 + free(ud.untracked);
3804 + free(ud.dirs);
3805 return -1;
3806 + }
3807
3808 *untracked_ = untracked = xmalloc(st_add3(sizeof(*untracked), eos - data, 1));
3809 memcpy(untracked, &ud, sizeof(ud));