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>
Patrick Steinhardt committed
Aug 22, 2024 at 11:17 UTC
f5ccb535ccfbabd55c2c7ab0b8e36ca5f322d31f
1 file changed
+38
-2
remote.c
+38
-2
@@ -243,6 +243,17 @@ static struct branch *make_branch(struct remote_state *remote_state,
243
return ret;
244
}
245
246
+static void branch_release(struct branch *branch)
247
+{
248
+ free((char *)branch->name);
249
+ free((char *)branch->refname);
250
+ free(branch->remote_name);
251
+ free(branch->pushremote_name);
252
+ for (int i = 0; i < branch->merge_nr; i++)
253
+ refspec_item_clear(branch->merge[i]);
254
+ free(branch->merge);
255
+}
256
+
257
static struct rewrite *make_rewrite(struct rewrites *r,
258
const char *base, size_t len)
259
{
@@ -263,6 +274,14 @@ static struct rewrite *make_rewrite(struct rewrites *r,
274
return ret;
275
}
276
277
+static void rewrites_release(struct rewrites *r)
278
+{
279
+ for (int i = 0; i < r->rewrite_nr; i++)
280
+ free((char *)r->rewrite[i]->base);
281
+ free(r->rewrite);
282
+ memset(r, 0, sizeof(*r));
283
+}
284
+
285
static void add_instead_of(struct rewrite *rewrite, const char *instead_of)
286
{
287
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,
392
return -1;
393
branch = make_branch(remote_state, name, namelen);
394
if (!strcmp(subkey, "remote")) {
395
+ FREE_AND_NULL(branch->remote_name);
396
return git_config_string(&branch->remote_name, key, value);
397
} else if (!strcmp(subkey, "pushremote")) {
398
+ FREE_AND_NULL(branch->pushremote_name);
399
return git_config_string(&branch->pushremote_name, key, value);
400
} else if (!strcmp(subkey, "merge")) {
401
if (!value)
@@ -406,9 +427,11 @@ static int handle_config(const char *key, const char *value,
427
return 0;
428
429
/* Handle remote.* variables */
409
- if (!name && !strcmp(subkey, "pushdefault"))
430
+ if (!name && !strcmp(subkey, "pushdefault")) {
431
+ FREE_AND_NULL(remote_state->pushremote_name);
432
return git_config_string(&remote_state->pushremote_name, key,
433
value);
434
+ }
435
436
if (!name)
437
return 0;
@@ -475,12 +498,15 @@ static int handle_config(const char *key, const char *value,
498
else if (!strcmp(value, "--tags"))
499
remote->fetch_tags = 2;
500
} else if (!strcmp(subkey, "proxy")) {
501
+ FREE_AND_NULL(remote->http_proxy);
502
return git_config_string(&remote->http_proxy,
503
key, value);
504
} else if (!strcmp(subkey, "proxyauthmethod")) {
505
+ FREE_AND_NULL(remote->http_proxy_authmethod);
506
return git_config_string(&remote->http_proxy_authmethod,
507
key, value);
508
} else if (!strcmp(subkey, "vcs")) {
509
+ FREE_AND_NULL(remote->foreign_vcs);
510
return git_config_string(&remote->foreign_vcs, key, value);
511
}
512
return 0;
@@ -2797,16 +2823,26 @@ struct remote_state *remote_state_new(void)
2823
2824
void remote_state_clear(struct remote_state *remote_state)
2825
{
2826
+ struct hashmap_iter iter;
2827
+ struct branch *b;
2828
int i;
2829
2830
for (i = 0; i < remote_state->remotes_nr; i++)
2831
remote_clear(remote_state->remotes[i]);
2832
FREE_AND_NULL(remote_state->remotes);
2833
+ FREE_AND_NULL(remote_state->pushremote_name);
2834
remote_state->remotes_alloc = 0;
2835
remote_state->remotes_nr = 0;
2836
2837
+ rewrites_release(&remote_state->rewrites);
2838
+ rewrites_release(&remote_state->rewrites_push);
2839
+
2840
hashmap_clear_and_free(&remote_state->remotes_hash, struct remote, ent);
2809
- hashmap_clear_and_free(&remote_state->branches_hash, struct remote, ent);
2841
+ hashmap_for_each_entry(&remote_state->branches_hash, &iter, b, ent) {
2842
+ branch_release(b);
2843
+ free(b);
2844
+ }
2845
+ hashmap_clear(&remote_state->branches_hash);
2846
}
2847
2848
/*