remote: fix leaking config strings

We're leaking several config strings when assembling remotes, either
because we do not free preceding values in case a config was set
multiple times, or because we do not free them when releasing the remote
state. This includes config strings for "branch" sections, "insteadOf",
"pushInsteadOf", and "pushDefault".

Plug those leaks.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Patrick Steinhardt
2024-08-22 11:17:55 +02:00
committed by Junio C Hamano
parent 46e440694f
commit f5ccb535cc

View File

@ -243,6 +243,17 @@ static struct branch *make_branch(struct remote_state *remote_state,
return ret;
}
static void branch_release(struct branch *branch)
{
free((char *)branch->name);
free((char *)branch->refname);
free(branch->remote_name);
free(branch->pushremote_name);
for (int i = 0; i < branch->merge_nr; i++)
refspec_item_clear(branch->merge[i]);
free(branch->merge);
}
static struct rewrite *make_rewrite(struct rewrites *r,
const char *base, size_t len)
{
@ -263,6 +274,14 @@ static struct rewrite *make_rewrite(struct rewrites *r,
return ret;
}
static void rewrites_release(struct rewrites *r)
{
for (int i = 0; i < r->rewrite_nr; i++)
free((char *)r->rewrite[i]->base);
free(r->rewrite);
memset(r, 0, sizeof(*r));
}
static void add_instead_of(struct rewrite *rewrite, const char *instead_of)
{
ALLOC_GROW(rewrite->instead_of, rewrite->instead_of_nr + 1, rewrite->instead_of_alloc);
@ -373,8 +392,10 @@ static int handle_config(const char *key, const char *value,
return -1;
branch = make_branch(remote_state, name, namelen);
if (!strcmp(subkey, "remote")) {
FREE_AND_NULL(branch->remote_name);
return git_config_string(&branch->remote_name, key, value);
} else if (!strcmp(subkey, "pushremote")) {
FREE_AND_NULL(branch->pushremote_name);
return git_config_string(&branch->pushremote_name, key, value);
} else if (!strcmp(subkey, "merge")) {
if (!value)
@ -406,9 +427,11 @@ static int handle_config(const char *key, const char *value,
return 0;
/* Handle remote.* variables */
if (!name && !strcmp(subkey, "pushdefault"))
if (!name && !strcmp(subkey, "pushdefault")) {
FREE_AND_NULL(remote_state->pushremote_name);
return git_config_string(&remote_state->pushremote_name, key,
value);
}
if (!name)
return 0;
@ -475,12 +498,15 @@ static int handle_config(const char *key, const char *value,
else if (!strcmp(value, "--tags"))
remote->fetch_tags = 2;
} else if (!strcmp(subkey, "proxy")) {
FREE_AND_NULL(remote->http_proxy);
return git_config_string(&remote->http_proxy,
key, value);
} else if (!strcmp(subkey, "proxyauthmethod")) {
FREE_AND_NULL(remote->http_proxy_authmethod);
return git_config_string(&remote->http_proxy_authmethod,
key, value);
} else if (!strcmp(subkey, "vcs")) {
FREE_AND_NULL(remote->foreign_vcs);
return git_config_string(&remote->foreign_vcs, key, value);
}
return 0;
@ -2797,16 +2823,26 @@ struct remote_state *remote_state_new(void)
void remote_state_clear(struct remote_state *remote_state)
{
struct hashmap_iter iter;
struct branch *b;
int i;
for (i = 0; i < remote_state->remotes_nr; i++)
remote_clear(remote_state->remotes[i]);
FREE_AND_NULL(remote_state->remotes);
FREE_AND_NULL(remote_state->pushremote_name);
remote_state->remotes_alloc = 0;
remote_state->remotes_nr = 0;
rewrites_release(&remote_state->rewrites);
rewrites_release(&remote_state->rewrites_push);
hashmap_clear_and_free(&remote_state->remotes_hash, struct remote, ent);
hashmap_clear_and_free(&remote_state->branches_hash, struct remote, ent);
hashmap_for_each_entry(&remote_state->branches_hash, &iter, b, ent) {
branch_release(b);
free(b);
}
hashmap_clear(&remote_state->branches_hash);
}
/*