name-rev: don't xstrdup() an already dup'd string

When "add_to_tip_table()" is called with a non-zero "shorten_unambiguous" we always return an xstrdup()'d string, which we'd then xstrdup() again, leaking memory. See [1] and [2] for how this leak came about. We could xstrdup() only if "shorten_unambiguous" wasn't true, but let's instead inline this code, so that information on whether we need to xstrdup() is contained within add_to_tip_table(). 1. 98c5c4ad015 (name-rev: allow to specify a subpath for --refs option, 2013-06-18) 2. b23e0b9353e (name-rev: allow converting the exact object name at the tip of a ref, 2013-07-07) Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ævar Arnfjörð Bjarmason committed Feb 7, 2023 at 00:07 UTC 486620ae0c4fd0c68cdd10140c769825d758564f
1 file changed +10 -13
builtin/name-rev.c
+10 -13
@@ -273,17 +273,6 @@ static int subpath_matches(const char *path, const char *filter)
273 return -1;
274 }
275
276 -static const char *name_ref_abbrev(const char *refname, int shorten_unambiguous)
277 -{
278 - if (shorten_unambiguous)
279 - refname = shorten_unambiguous_ref(refname, 0);
280 - else if (skip_prefix(refname, "refs/heads/", &refname))
281 - ; /* refname already advanced */
282 - else
283 - skip_prefix(refname, "refs/", &refname);
284 - return refname;
285 -}
286 -
276 struct name_ref_data {
277 int tags_only;
278 int name_only;
@@ -309,11 +298,19 @@ static void add_to_tip_table(const struct object_id *oid, const char *refname,
298 int shorten_unambiguous, struct commit *commit,
299 timestamp_t taggerdate, int from_tag, int deref)
300 {
312 - refname = name_ref_abbrev(refname, shorten_unambiguous);
301 + char *short_refname = NULL;
302 +
303 + if (shorten_unambiguous)
304 + short_refname = shorten_unambiguous_ref(refname, 0);
305 + else if (skip_prefix(refname, "refs/heads/", &refname))
306 + ; /* refname already advanced */
307 + else
308 + skip_prefix(refname, "refs/", &refname);
309
310 ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
311 oidcpy(&tip_table.table[tip_table.nr].oid, oid);
316 - tip_table.table[tip_table.nr].refname = xstrdup(refname);
312 + tip_table.table[tip_table.nr].refname = short_refname ?
313 + short_refname : xstrdup(refname);
314 tip_table.table[tip_table.nr].commit = commit;
315 tip_table.table[tip_table.nr].taggerdate = taggerdate;
316 tip_table.table[tip_table.nr].from_tag = from_tag;