Skip to content

Commit 30035d9

Browse files
rscharfegitster
authored andcommitted
push: release strbufs used for refspec formatting
map_refspec() either returns the passed in ref string or a detached strbuf. This makes it hard for callers to release the possibly allocated memory, and set_refspecs() consequently leaks it. Let map_refspec() append any refspecs directly and release its own strbufs after use. Rename it to refspec_append_mapped() and don't return anything to reflect its increased responsibility. set_refspecs() also leaks its strbufs. Do the same here and directly call refspec_append() in each if branch instead of holding onto a detached strbuf, then dispose of the allocated memory after use. We need to add an else branch for the final call because all the other conditional branches already add their formatted refspec now. setup_push_upstream() and setup_push_current() forgot to release their strbufs as well; plug these leaks, too, while at it. None of these leaks were likely to impact users, because the number and sizes of refspecs are usually small and the allocations are only done once per program run. Clean them up nevertheless, as another step on the long road towards zero memory leaks. Signed-off-by: René Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 3a238e5 commit 30035d9

File tree

1 file changed

+22
-12
lines changed

1 file changed

+22
-12
lines changed

builtin/push.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,17 @@ static struct refspec rs = REFSPEC_INIT_PUSH;
6161

6262
static struct string_list push_options_config = STRING_LIST_INIT_DUP;
6363

64-
static const char *map_refspec(const char *ref,
65-
struct remote *remote, struct ref *local_refs)
64+
static void refspec_append_mapped(struct refspec *refspec, const char *ref,
65+
struct remote *remote, struct ref *local_refs)
6666
{
6767
const char *branch_name;
6868
struct ref *matched = NULL;
6969

7070
/* Does "ref" uniquely name our ref? */
71-
if (count_refspec_match(ref, local_refs, &matched) != 1)
72-
return ref;
71+
if (count_refspec_match(ref, local_refs, &matched) != 1) {
72+
refspec_append(refspec, ref);
73+
return;
74+
}
7375

7476
if (remote->push.nr) {
7577
struct refspec_item query;
@@ -80,7 +82,9 @@ static const char *map_refspec(const char *ref,
8082
strbuf_addf(&buf, "%s%s:%s",
8183
query.force ? "+" : "",
8284
query.src, query.dst);
83-
return strbuf_detach(&buf, NULL);
85+
refspec_append(refspec, buf.buf);
86+
strbuf_release(&buf);
87+
return;
8488
}
8589
}
8690

@@ -91,11 +95,13 @@ static const char *map_refspec(const char *ref,
9195
struct strbuf buf = STRBUF_INIT;
9296
strbuf_addf(&buf, "%s:%s",
9397
ref, branch->merge[0]->src);
94-
return strbuf_detach(&buf, NULL);
98+
refspec_append(refspec, buf.buf);
99+
strbuf_release(&buf);
100+
return;
95101
}
96102
}
97103

98-
return ref;
104+
refspec_append(refspec, ref);
99105
}
100106

101107
static void set_refspecs(const char **refs, int nr, const char *repo)
@@ -115,22 +121,24 @@ static void set_refspecs(const char **refs, int nr, const char *repo)
115121
strbuf_addf(&tagref, ":refs/tags/%s", ref);
116122
else
117123
strbuf_addf(&tagref, "refs/tags/%s", ref);
118-
ref = strbuf_detach(&tagref, NULL);
124+
refspec_append(&rs, tagref.buf);
125+
strbuf_release(&tagref);
119126
} else if (deleterefs) {
120127
struct strbuf delref = STRBUF_INIT;
121128
if (strchr(ref, ':'))
122129
die(_("--delete only accepts plain target ref names"));
123130
strbuf_addf(&delref, ":%s", ref);
124-
ref = strbuf_detach(&delref, NULL);
131+
refspec_append(&rs, delref.buf);
132+
strbuf_release(&delref);
125133
} else if (!strchr(ref, ':')) {
126134
if (!remote) {
127135
/* lazily grab remote and local_refs */
128136
remote = remote_get(repo);
129137
local_refs = get_local_heads();
130138
}
131-
ref = map_refspec(ref, remote, local_refs);
132-
}
133-
refspec_append(&rs, ref);
139+
refspec_append_mapped(&rs, ref, remote, local_refs);
140+
} else
141+
refspec_append(&rs, ref);
134142
}
135143
}
136144

@@ -221,6 +229,7 @@ static void setup_push_upstream(struct remote *remote, struct branch *branch,
221229

222230
strbuf_addf(&refspec, "%s:%s", branch->refname, branch->merge[0]->src);
223231
refspec_append(&rs, refspec.buf);
232+
strbuf_release(&refspec);
224233
}
225234

226235
static void setup_push_current(struct remote *remote, struct branch *branch)
@@ -231,6 +240,7 @@ static void setup_push_current(struct remote *remote, struct branch *branch)
231240
die(_(message_detached_head_die), remote->name);
232241
strbuf_addf(&refspec, "%s:%s", branch->refname, branch->refname);
233242
refspec_append(&rs, refspec.buf);
243+
strbuf_release(&refspec);
234244
}
235245

236246
static int is_workflow_triangular(struct remote *remote)

0 commit comments

Comments
 (0)