Skip to content

Commit 31bc445

Browse files
committed
Merge branch 'ps/leakfixes-part-8'
More leakfixes. * ps/leakfixes-part-8: (23 commits) builtin/send-pack: fix leaking list of push options remote: fix leaking push reports t/helper: fix leaks in proc-receive helper pack-write: fix return parameter of `write_rev_file_order()` revision: fix leaking saved parents revision: fix memory leaks when rewriting parents midx-write: fix leaking buffer pack-bitmap-write: fix leaking OID array pseudo-merge: fix leaking strmap keys pseudo-merge: fix various memory leaks line-log: fix several memory leaks diff: improve lifecycle management of diff queues builtin/revert: fix leaking `gpg_sign` and `strategy` config t/helper: fix leaking repository in partial-clone helper builtin/clone: fix leaking repo state when cloning with bundle URIs builtin/pack-redundant: fix various memory leaks builtin/stash: fix leaking `pathspec_from_file` submodule: fix leaking submodule entry list wt-status: fix leaking buffer with sparse directories shell: fix leaking strings ...
2 parents d29d644 + 66893a1 commit 31bc445

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+329
-123
lines changed

bloom.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,6 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
476476
*last_slash = '\0';
477477

478478
} while (*path);
479-
480-
diff_free_filepair(diff_queued_diff.queue[i]);
481479
}
482480

483481
if (hashmap_get_size(&pathmap) > settings->max_changed_paths) {
@@ -508,8 +506,6 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
508506
cleanup:
509507
hashmap_clear_and_free(&pathmap, struct pathmap_hash_entry, entry);
510508
} else {
511-
for (i = 0; i < diff_queued_diff.nr; i++)
512-
diff_free_filepair(diff_queued_diff.queue[i]);
513509
init_truncated_large_filter(filter, settings->hash_version);
514510

515511
if (computed)
@@ -519,9 +515,7 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
519515
if (computed)
520516
*computed |= BLOOM_COMPUTED;
521517

522-
free(diff_queued_diff.queue);
523-
DIFF_QUEUE_CLEAR(&diff_queued_diff);
524-
518+
diff_queue_clear(&diff_queued_diff);
525519
return filter;
526520
}
527521

branch.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,7 @@ static int submodule_create_branch(struct repository *r,
738738

739739
strbuf_release(&child_err);
740740
strbuf_release(&out_buf);
741+
free(out_prefix);
741742
return ret;
742743
}
743744

@@ -794,7 +795,7 @@ void create_branches_recursively(struct repository *r, const char *name,
794795
create_branch(r, name, start_committish, force, 0, reflog, quiet,
795796
BRANCH_TRACK_NEVER, dry_run);
796797
if (dry_run)
797-
return;
798+
goto out;
798799
/*
799800
* NEEDSWORK If tracking was set up in the superproject but not the
800801
* submodule, users might expect "git branch --recurse-submodules" to
@@ -815,8 +816,11 @@ void create_branches_recursively(struct repository *r, const char *name,
815816
die(_("submodule '%s': cannot create branch '%s'"),
816817
submodule_entry_list.entries[i].submodule->name,
817818
name);
818-
repo_clear(submodule_entry_list.entries[i].repo);
819819
}
820+
821+
out:
822+
submodule_entry_list_release(&submodule_entry_list);
823+
free(branch_point);
820824
}
821825

822826
void remove_merge_branch_state(struct repository *r)

builtin/annotate.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,23 @@ int cmd_annotate(int argc,
1515
struct repository *repo UNUSED)
1616
{
1717
struct strvec args = STRVEC_INIT;
18-
int i;
18+
const char **args_copy;
19+
int ret;
1920

2021
strvec_pushl(&args, "annotate", "-c", NULL);
21-
22-
for (i = 1; i < argc; i++) {
22+
for (int i = 1; i < argc; i++)
2323
strvec_push(&args, argv[i]);
24-
}
2524

26-
return cmd_blame(args.nr, args.v, prefix, the_repository);
25+
/*
26+
* `cmd_blame()` ends up modifying the array, which causes memory leaks
27+
* if we didn't copy the array here.
28+
*/
29+
CALLOC_ARRAY(args_copy, args.nr + 1);
30+
COPY_ARRAY(args_copy, args.v, args.nr);
31+
32+
ret = cmd_blame(args.nr, args_copy, prefix, the_repository);
33+
34+
strvec_clear(&args);
35+
free(args_copy);
36+
return ret;
2737
}

builtin/clone.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,8 +1403,17 @@ int cmd_clone(int argc,
14031403
* data from the --bundle-uri option.
14041404
*/
14051405
if (bundle_uri) {
1406+
struct remote_state *state;
14061407
int has_heuristic = 0;
14071408

1409+
/*
1410+
* We need to save the remote state as our remote's lifetime is
1411+
* tied to it.
1412+
*/
1413+
state = the_repository->remote_state;
1414+
the_repository->remote_state = NULL;
1415+
repo_clear(the_repository);
1416+
14081417
/* At this point, we need the_repository to match the cloned repo. */
14091418
if (repo_init(the_repository, git_dir, work_tree))
14101419
warning(_("failed to initialize the repo, skipping bundle URI"));
@@ -1413,6 +1422,10 @@ int cmd_clone(int argc,
14131422
bundle_uri);
14141423
else if (has_heuristic)
14151424
git_config_set_gently("fetch.bundleuri", bundle_uri);
1425+
1426+
remote_state_clear(the_repository->remote_state);
1427+
free(the_repository->remote_state);
1428+
the_repository->remote_state = state;
14161429
} else {
14171430
/*
14181431
* Populate transport->got_remote_bundle_uri and
@@ -1422,12 +1435,26 @@ int cmd_clone(int argc,
14221435

14231436
if (transport->bundles &&
14241437
hashmap_get_size(&transport->bundles->bundles)) {
1438+
struct remote_state *state;
1439+
1440+
/*
1441+
* We need to save the remote state as our remote's
1442+
* lifetime is tied to it.
1443+
*/
1444+
state = the_repository->remote_state;
1445+
the_repository->remote_state = NULL;
1446+
repo_clear(the_repository);
1447+
14251448
/* At this point, we need the_repository to match the cloned repo. */
14261449
if (repo_init(the_repository, git_dir, work_tree))
14271450
warning(_("failed to initialize the repo, skipping bundle URI"));
14281451
else if (fetch_bundle_list(the_repository,
14291452
transport->bundles))
14301453
warning(_("failed to fetch advertised bundles"));
1454+
1455+
remote_state_clear(the_repository->remote_state);
1456+
free(the_repository->remote_state);
1457+
the_repository->remote_state = state;
14311458
} else {
14321459
clear_bundle_list(transport->bundles);
14331460
FREE_AND_NULL(transport->bundles);

builtin/index-pack.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,7 +1505,7 @@ static void rename_tmp_packfile(const char **final_name,
15051505
struct strbuf *name, unsigned char *hash,
15061506
const char *ext, int make_read_only_if_same)
15071507
{
1508-
if (*final_name != curr_name) {
1508+
if (!*final_name || strcmp(*final_name, curr_name)) {
15091509
if (!*final_name)
15101510
*final_name = odb_pack_name(name, hash, ext);
15111511
if (finalize_object_file(curr_name, *final_name))
@@ -1726,7 +1726,7 @@ int cmd_index_pack(int argc,
17261726
{
17271727
int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index;
17281728
const char *curr_index;
1729-
const char *curr_rev_index = NULL;
1729+
char *curr_rev_index = NULL;
17301730
const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL;
17311731
const char *keep_msg = NULL;
17321732
const char *promisor_msg = NULL;
@@ -1968,8 +1968,7 @@ int cmd_index_pack(int argc,
19681968
free((void *) curr_pack);
19691969
if (!index_name)
19701970
free((void *) curr_index);
1971-
if (!rev_index_name)
1972-
free((void *) curr_rev_index);
1971+
free(curr_rev_index);
19731972

19741973
/*
19751974
* Let the caller know this pack is not self contained

builtin/pack-redundant.c

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,15 @@ static inline void llist_init(struct llist **list)
6969
(*list)->size = 0;
7070
}
7171

72+
static void llist_free(struct llist *list)
73+
{
74+
for (struct llist_item *i = list->front, *next; i; i = next) {
75+
next = i->next;
76+
llist_item_put(i);
77+
}
78+
free(list);
79+
}
80+
7281
static struct llist * llist_copy(struct llist *list)
7382
{
7483
struct llist *ret;
@@ -206,6 +215,14 @@ static inline struct pack_list * pack_list_insert(struct pack_list **pl,
206215
return p;
207216
}
208217

218+
static void pack_list_free(struct pack_list *pl)
219+
{
220+
for (struct pack_list *next; pl; pl = next) {
221+
next = pl->next;
222+
free(pl);
223+
}
224+
}
225+
209226
static inline size_t pack_list_size(struct pack_list *pl)
210227
{
211228
size_t ret = 0;
@@ -419,7 +436,8 @@ static void minimize(struct pack_list **min)
419436

420437
/* return if there are no objects missing from the unique set */
421438
if (missing->size == 0) {
422-
free(missing);
439+
llist_free(missing);
440+
pack_list_free(non_unique);
423441
return;
424442
}
425443

@@ -434,6 +452,8 @@ static void minimize(struct pack_list **min)
434452
}
435453

436454
while (non_unique) {
455+
struct pack_list *next;
456+
437457
/* sort the non_unique packs, greater size of remaining_objects first */
438458
sort_pack_list(&non_unique);
439459
if (non_unique->remaining_objects->size == 0)
@@ -444,8 +464,14 @@ static void minimize(struct pack_list **min)
444464
for (pl = non_unique->next; pl && pl->remaining_objects->size > 0; pl = pl->next)
445465
llist_sorted_difference_inplace(pl->remaining_objects, non_unique->remaining_objects);
446466

447-
non_unique = non_unique->next;
467+
next = non_unique->next;
468+
free(non_unique);
469+
non_unique = next;
448470
}
471+
472+
pack_list_free(non_unique);
473+
llist_free(unique_pack_objects);
474+
llist_free(missing);
449475
}
450476

451477
static void load_all_objects(void)
@@ -565,7 +591,6 @@ static void load_all(void)
565591
int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) {
566592
int i; int i_still_use_this = 0; struct pack_list *min = NULL, *red, *pl;
567593
struct llist *ignore;
568-
struct object_id *oid;
569594
char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */
570595

571596
if (argc == 2 && !strcmp(argv[1], "-h"))
@@ -625,11 +650,11 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, s
625650
/* ignore objects given on stdin */
626651
llist_init(&ignore);
627652
if (!isatty(0)) {
653+
struct object_id oid;
628654
while (fgets(buf, sizeof(buf), stdin)) {
629-
oid = xmalloc(sizeof(*oid));
630-
if (get_oid_hex(buf, oid))
655+
if (get_oid_hex(buf, &oid))
631656
die("Bad object ID on stdin: %s", buf);
632-
llist_insert_sorted_unique(ignore, oid, NULL);
657+
llist_insert_sorted_unique(ignore, &oid, NULL);
633658
}
634659
}
635660
llist_sorted_difference_inplace(all_objects, ignore);
@@ -671,5 +696,8 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, s
671696
fprintf(stderr, "%luMB of redundant packs in total.\n",
672697
(unsigned long)pack_set_bytecount(red)/(1024*1024));
673698

699+
pack_list_free(red);
700+
pack_list_free(min);
701+
llist_free(ignore);
674702
return 0;
675703
}

builtin/receive-pack.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ static void write_head_info(void)
374374
struct command {
375375
struct command *next;
376376
const char *error_string;
377+
char *error_string_owned;
377378
struct ref_push_report *report;
378379
unsigned int skip_update:1,
379380
did_not_exist:1,
@@ -1083,7 +1084,7 @@ static int read_proc_receive_report(struct packet_reader *reader,
10831084
hint->run_proc_receive |= RUN_PROC_RECEIVE_RETURNED;
10841085
if (!strcmp(head, "ng")) {
10851086
if (p)
1086-
hint->error_string = xstrdup(p);
1087+
hint->error_string = hint->error_string_owned = xstrdup(p);
10871088
else
10881089
hint->error_string = "failed";
10891090
code = -1;
@@ -2054,6 +2055,8 @@ static void free_commands(struct command *commands)
20542055
while (commands) {
20552056
struct command *next = commands->next;
20562057

2058+
ref_push_report_free(commands->report);
2059+
free(commands->error_string_owned);
20572060
free(commands);
20582061
commands = next;
20592062
}

builtin/revert.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
110110
const char * const * usage_str = revert_or_cherry_pick_usage(opts);
111111
const char *me = action_name(opts);
112112
const char *cleanup_arg = NULL;
113+
const char sentinel_value;
114+
const char *strategy = &sentinel_value;
115+
const char *gpg_sign = &sentinel_value;
113116
enum empty_action empty_opt = EMPTY_COMMIT_UNSPECIFIED;
114117
int cmd = 0;
115118
struct option base_options[] = {
@@ -125,10 +128,10 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
125128
OPT_CALLBACK('m', "mainline", opts, N_("parent-number"),
126129
N_("select mainline parent"), option_parse_m),
127130
OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto),
128-
OPT_STRING(0, "strategy", &opts->strategy, N_("strategy"), N_("merge strategy")),
131+
OPT_STRING(0, "strategy", &strategy, N_("strategy"), N_("merge strategy")),
129132
OPT_STRVEC('X', "strategy-option", &opts->xopts, N_("option"),
130133
N_("option for merge strategy")),
131-
{ OPTION_STRING, 'S', "gpg-sign", &opts->gpg_sign, N_("key-id"),
134+
{ OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),
132135
N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
133136
OPT_END()
134137
};
@@ -240,8 +243,14 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
240243
usage_with_options(usage_str, options);
241244

242245
/* These option values will be free()d */
243-
opts->gpg_sign = xstrdup_or_null(opts->gpg_sign);
244-
opts->strategy = xstrdup_or_null(opts->strategy);
246+
if (gpg_sign != &sentinel_value) {
247+
free(opts->gpg_sign);
248+
opts->gpg_sign = xstrdup_or_null(gpg_sign);
249+
}
250+
if (strategy != &sentinel_value) {
251+
free(opts->strategy);
252+
opts->strategy = xstrdup_or_null(strategy);
253+
}
245254
if (!opts->strategy && getenv("GIT_TEST_MERGE_ALGORITHM"))
246255
opts->strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM"));
247256
free(options);

builtin/send-pack.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ int cmd_send_pack(int argc,
340340
/* stable plumbing output; do not modify or localize */
341341
fprintf(stderr, "Everything up-to-date\n");
342342

343+
string_list_clear(&push_options, 0);
343344
free_refs(remote_refs);
344345
free_refs(local_refs);
345346
refspec_clear(&rs);

builtin/stash.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1759,7 +1759,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
17591759
int quiet = 0;
17601760
int pathspec_file_nul = 0;
17611761
const char *stash_msg = NULL;
1762-
const char *pathspec_from_file = NULL;
1762+
char *pathspec_from_file = NULL;
17631763
struct pathspec ps;
17641764
struct option options[] = {
17651765
OPT_BOOL('k', "keep-index", &keep_index,
@@ -1821,7 +1821,9 @@ static int push_stash(int argc, const char **argv, const char *prefix,
18211821

18221822
ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
18231823
include_untracked, only_staged);
1824+
18241825
clear_pathspec(&ps);
1826+
free(pathspec_from_file);
18251827
return ret;
18261828
}
18271829

0 commit comments

Comments
 (0)