Skip to content

Commit f046127

Browse files
peffgitster
authored andcommitted
ref-filter: fix leak when formatting %(push:remoteref)
When we expand the %(upstream) or %(push) placeholders, we rely on remote.c's remote_ref_for_branch() to fill in the ":refname" argument. But that function has confusing memory ownership semantics: it may or may not return an allocated string, depending on whether we are in "upstream" mode or "push" mode. The caller in ref-filter.c always duplicates the result, meaning that we leak the original in the case of %(push:refname). To solve this, let's make the return value from remote_ref_for_branch() consistent, by always returning an allocated pointer. Note that the switch to returning a non-const pointer has a ripple effect inside the function, too. We were storing the "dst" result as a const pointer, too, even though it is always allocated! It is the return value from apply_refspecs(), which is always a non-const allocated string. And then on the caller side in ref-filter.c (and this is the only caller at all), we just need to avoid the extra duplication when the return value is non-NULL. This clears up one case that LSan finds in t6300, but there are more. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ec007cd commit f046127

File tree

3 files changed

+6
-6
lines changed

3 files changed

+6
-6
lines changed

ref-filter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2237,7 +2237,7 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *refname,
22372237
const char *merge;
22382238

22392239
merge = remote_ref_for_branch(branch, atom->u.remote_ref.push);
2240-
*s = xstrdup(merge ? merge : "");
2240+
*s = merge ? merge : xstrdup("");
22412241
} else
22422242
BUG("unhandled RR_* enum");
22432243
}

remote.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -632,19 +632,19 @@ const char *pushremote_for_branch(struct branch *branch, int *explicit)
632632
static struct remote *remotes_remote_get(struct remote_state *remote_state,
633633
const char *name);
634634

635-
const char *remote_ref_for_branch(struct branch *branch, int for_push)
635+
char *remote_ref_for_branch(struct branch *branch, int for_push)
636636
{
637637
read_config(the_repository, 0);
638638
die_on_missing_branch(the_repository, branch);
639639

640640
if (branch) {
641641
if (!for_push) {
642642
if (branch->merge_nr) {
643-
return branch->merge_name[0];
643+
return xstrdup(branch->merge_name[0]);
644644
}
645645
} else {
646-
const char *dst,
647-
*remote_name = remotes_pushremote_for_branch(
646+
char *dst;
647+
const char *remote_name = remotes_pushremote_for_branch(
648648
the_repository->remote_state, branch,
649649
NULL);
650650
struct remote *remote = remotes_remote_get(

remote.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ struct branch {
329329
struct branch *branch_get(const char *name);
330330
const char *remote_for_branch(struct branch *branch, int *explicit);
331331
const char *pushremote_for_branch(struct branch *branch, int *explicit);
332-
const char *remote_ref_for_branch(struct branch *branch, int for_push);
332+
char *remote_ref_for_branch(struct branch *branch, int for_push);
333333

334334
/* returns true if the given branch has merge configuration given. */
335335
int branch_has_merge_config(struct branch *branch);

0 commit comments

Comments
 (0)