run_diff_files(): delay allocation of combine_diff_path

While looping over the index entries, when we see a higher level stage the first thing we do is allocate a combine_diff_path struct for it. But this can leak; if check_removed() returns an error, we'll continue to the next iteration of the loop without cleaning up. We can fix this by just delaying the allocation by a few lines. I don't think this leak is triggered in the test suite, but it's pretty easy to see by inspection. My ulterior motive here is that the delayed allocation means we have all of the data needed to initialize "dpath" at the time of malloc, making it easier to factor out a constructor function. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Jan 9, 2025 at 03:28 UTC 949bb8f74f6db7405d6ad8bbf02ebc42a947801d
1 file changed +12 -12
diff-lib.c
+12 -12
@@ -156,18 +156,6 @@ void run_diff_files(struct rev_info *revs, unsigned int option)
156 size_t path_len;
157 struct stat st;
158
159 - path_len = ce_namelen(ce);
160 -
161 - dpath = xmalloc(combine_diff_path_size(5, path_len));
162 - dpath->path = (char *) &(dpath->parent[5]);
163 -
164 - dpath->next = NULL;
165 - memcpy(dpath->path, ce->name, path_len);
166 - dpath->path[path_len] = '\0';
167 - oidclr(&dpath->oid, the_repository->hash_algo);
168 - memset(&(dpath->parent[0]), 0,
169 - sizeof(struct combine_diff_parent)*5);
170 -
159 changed = check_removed(ce, &st);
160 if (!changed)
161 wt_mode = ce_mode_from_stat(ce, st.st_mode);
@@ -178,7 +166,19 @@ void run_diff_files(struct rev_info *revs, unsigned int option)
166 }
167 wt_mode = 0;
168 }
169 +
170 + path_len = ce_namelen(ce);
171 +
172 + dpath = xmalloc(combine_diff_path_size(5, path_len));
173 + dpath->path = (char *) &(dpath->parent[5]);
174 +
175 + dpath->next = NULL;
176 + memcpy(dpath->path, ce->name, path_len);
177 + dpath->path[path_len] = '\0';
178 + oidclr(&dpath->oid, the_repository->hash_algo);
179 dpath->mode = wt_mode;
180 + memset(&(dpath->parent[0]), 0,
181 + sizeof(struct combine_diff_parent)*5);
182
183 while (i < entries) {
184 struct cache_entry *nce = istate->cache[i];