Skip to content

Commit 44357f6

Browse files
committed
Merge branch 'ab/leakfix'
Plug various memory leaks. * ab/leakfix: pull: fix a "struct oid_array" memory leak cat-file: fix a common "struct object_context" memory leak gc: fix a memory leak checkout: avoid "struct unpack_trees_options" leak merge-file: fix memory leaks on error path merge-file: refactor for subsequent memory leak fix cat-file: fix a memory leak in --batch-command mode revert: free "struct replay_opts" members submodule.c: free() memory from xgetcwd() clone: fix memory leak in wanted_peer_refs() check-ref-format: fix trivial memory leak
2 parents f01315e + ece3974 commit 44357f6

26 files changed

+114
-54
lines changed

builtin/cat-file.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ static int stream_blob(const struct object_id *oid)
7171
static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
7272
int unknown_type)
7373
{
74+
int ret;
7475
struct object_id oid;
7576
enum object_type type;
7677
char *buf;
@@ -106,7 +107,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
106107
if (sb.len) {
107108
printf("%s\n", sb.buf);
108109
strbuf_release(&sb);
109-
return 0;
110+
ret = 0;
111+
goto cleanup;
110112
}
111113
break;
112114

@@ -115,16 +117,19 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
115117
if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
116118
die("git cat-file: could not get object info");
117119
printf("%"PRIuMAX"\n", (uintmax_t)size);
118-
return 0;
120+
ret = 0;
121+
goto cleanup;
119122

120123
case 'e':
121124
return !has_object_file(&oid);
122125

123126
case 'w':
124127

125128
if (filter_object(path, obj_context.mode,
126-
&oid, &buf, &size))
127-
return -1;
129+
&oid, &buf, &size)) {
130+
ret = -1;
131+
goto cleanup;
132+
}
128133
break;
129134

130135
case 'c':
@@ -143,11 +148,14 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
143148
const char *ls_args[3] = { NULL };
144149
ls_args[0] = "ls-tree";
145150
ls_args[1] = obj_name;
146-
return cmd_ls_tree(2, ls_args, NULL);
151+
ret = cmd_ls_tree(2, ls_args, NULL);
152+
goto cleanup;
147153
}
148154

149-
if (type == OBJ_BLOB)
150-
return stream_blob(&oid);
155+
if (type == OBJ_BLOB) {
156+
ret = stream_blob(&oid);
157+
goto cleanup;
158+
}
151159
buf = read_object_file(&oid, &type, &size);
152160
if (!buf)
153161
die("Cannot read object %s", obj_name);
@@ -172,8 +180,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
172180
} else
173181
oidcpy(&blob_oid, &oid);
174182

175-
if (oid_object_info(the_repository, &blob_oid, NULL) == OBJ_BLOB)
176-
return stream_blob(&blob_oid);
183+
if (oid_object_info(the_repository, &blob_oid, NULL) == OBJ_BLOB) {
184+
ret = stream_blob(&blob_oid);
185+
goto cleanup;
186+
}
177187
/*
178188
* we attempted to dereference a tag to a blob
179189
* and failed; there may be new dereference
@@ -193,9 +203,11 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
193203
die("git cat-file %s: bad file", obj_name);
194204

195205
write_or_die(1, buf, size);
206+
ret = 0;
207+
cleanup:
196208
free(buf);
197209
free(obj_context.path);
198-
return 0;
210+
return ret;
199211
}
200212

201213
struct expand_data {
@@ -655,6 +667,7 @@ static void batch_objects_command(struct batch_options *opt,
655667
free_cmds(queued_cmd, &nr);
656668
}
657669

670+
free_cmds(queued_cmd, &nr);
658671
free(queued_cmd);
659672
strbuf_release(&input);
660673
}

builtin/check-ref-format.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
5757
int normalize = 0;
5858
int flags = 0;
5959
const char *refname;
60+
char *to_free = NULL;
61+
int ret = 1;
6062

6163
if (argc == 2 && !strcmp(argv[1], "-h"))
6264
usage(builtin_check_ref_format_usage);
@@ -81,11 +83,14 @@ int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
8183

8284
refname = argv[i];
8385
if (normalize)
84-
refname = collapse_slashes(refname);
86+
refname = to_free = collapse_slashes(refname);
8587
if (check_refname_format(refname, flags))
86-
return 1;
88+
goto cleanup;
8789
if (normalize)
8890
printf("%s\n", refname);
8991

90-
return 0;
92+
ret = 0;
93+
cleanup:
94+
free(to_free);
95+
return ret;
9196
}

builtin/checkout.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,26 @@ static void setup_branch_path(struct branch_info *branch)
710710
branch->path = strbuf_detach(&buf, NULL);
711711
}
712712

713+
static void init_topts(struct unpack_trees_options *topts, int merge,
714+
int show_progress, int overwrite_ignore,
715+
struct commit *old_commit)
716+
{
717+
memset(topts, 0, sizeof(*topts));
718+
topts->head_idx = -1;
719+
topts->src_index = &the_index;
720+
topts->dst_index = &the_index;
721+
722+
setup_unpack_trees_porcelain(topts, "checkout");
723+
724+
topts->initial_checkout = is_cache_unborn();
725+
topts->update = 1;
726+
topts->merge = 1;
727+
topts->quiet = merge && old_commit;
728+
topts->verbose_update = show_progress;
729+
topts->fn = twoway_merge;
730+
topts->preserve_ignored = !overwrite_ignore;
731+
}
732+
713733
static int merge_working_tree(const struct checkout_opts *opts,
714734
struct branch_info *old_branch_info,
715735
struct branch_info *new_branch_info,
@@ -740,13 +760,6 @@ static int merge_working_tree(const struct checkout_opts *opts,
740760
struct unpack_trees_options topts;
741761
const struct object_id *old_commit_oid;
742762

743-
memset(&topts, 0, sizeof(topts));
744-
topts.head_idx = -1;
745-
topts.src_index = &the_index;
746-
topts.dst_index = &the_index;
747-
748-
setup_unpack_trees_porcelain(&topts, "checkout");
749-
750763
refresh_cache(REFRESH_QUIET);
751764

752765
if (unmerged_cache()) {
@@ -755,17 +768,12 @@ static int merge_working_tree(const struct checkout_opts *opts,
755768
}
756769

757770
/* 2-way merge to the new branch */
758-
topts.initial_checkout = is_cache_unborn();
759-
topts.update = 1;
760-
topts.merge = 1;
761-
topts.quiet = opts->merge && old_branch_info->commit;
762-
topts.verbose_update = opts->show_progress;
763-
topts.fn = twoway_merge;
771+
init_topts(&topts, opts->merge, opts->show_progress,
772+
opts->overwrite_ignore, old_branch_info->commit);
764773
init_checkout_metadata(&topts.meta, new_branch_info->refname,
765774
new_branch_info->commit ?
766775
&new_branch_info->commit->object.oid :
767776
&new_branch_info->oid, NULL);
768-
topts.preserve_ignored = !opts->overwrite_ignore;
769777

770778
old_commit_oid = old_branch_info->commit ?
771779
&old_branch_info->commit->object.oid :

builtin/clone.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ static struct ref *wanted_peer_refs(const struct ref *refs,
494494
/* if --branch=tag, pull the requested tag explicitly */
495495
get_fetch_map(remote_head, tag_refspec, &tail, 0);
496496
}
497+
free_refs(remote_head);
497498
} else {
498499
int i;
499500
for (i = 0; i < refspec->nr; i++)

builtin/gc.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,15 @@ struct maintenance_run_opts;
168168
static int maintenance_task_pack_refs(MAYBE_UNUSED struct maintenance_run_opts *opts)
169169
{
170170
struct strvec pack_refs_cmd = STRVEC_INIT;
171+
int ret;
172+
171173
strvec_pushl(&pack_refs_cmd, "pack-refs", "--all", "--prune", NULL);
172174

173-
return run_command_v_opt(pack_refs_cmd.v, RUN_GIT_CMD);
175+
ret = run_command_v_opt(pack_refs_cmd.v, RUN_GIT_CMD);
176+
177+
strvec_clear(&pack_refs_cmd);
178+
179+
return ret;
174180
}
175181

176182
static int too_many_loose_objects(void)

builtin/merge-file.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ static int label_cb(const struct option *opt, const char *arg, int unset)
2525

2626
int cmd_merge_file(int argc, const char **argv, const char *prefix)
2727
{
28-
const char *names[3] = { NULL, NULL, NULL };
29-
mmfile_t mmfs[3];
30-
mmbuffer_t result = {NULL, 0};
31-
xmparam_t xmp = {{0}};
28+
const char *names[3] = { 0 };
29+
mmfile_t mmfs[3] = { 0 };
30+
mmbuffer_t result = { 0 };
31+
xmparam_t xmp = { 0 };
3232
int ret = 0, i = 0, to_stdout = 0;
3333
int quiet = 0;
3434
struct option options[] = {
@@ -71,31 +71,31 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
7171

7272
for (i = 0; i < 3; i++) {
7373
char *fname;
74-
int ret;
74+
mmfile_t *mmf = mmfs + i;
7575

7676
if (!names[i])
7777
names[i] = argv[i];
7878

7979
fname = prefix_filename(prefix, argv[i]);
80-
ret = read_mmfile(mmfs + i, fname);
80+
81+
if (read_mmfile(mmf, fname))
82+
ret = -1;
83+
else if (mmf->size > MAX_XDIFF_SIZE ||
84+
buffer_is_binary(mmf->ptr, mmf->size))
85+
ret = error("Cannot merge binary files: %s",
86+
argv[i]);
87+
8188
free(fname);
8289
if (ret)
83-
return -1;
90+
goto cleanup;
8491

85-
if (mmfs[i].size > MAX_XDIFF_SIZE ||
86-
buffer_is_binary(mmfs[i].ptr, mmfs[i].size))
87-
return error("Cannot merge binary files: %s",
88-
argv[i]);
8992
}
9093

9194
xmp.ancestor = names[1];
9295
xmp.file1 = names[0];
9396
xmp.file2 = names[2];
9497
ret = xdl_merge(mmfs + 1, mmfs + 0, mmfs + 2, &xmp, &result);
9598

96-
for (i = 0; i < 3; i++)
97-
free(mmfs[i].ptr);
98-
9999
if (ret >= 0) {
100100
const char *filename = argv[0];
101101
char *fpath = prefix_filename(prefix, argv[0]);
@@ -116,5 +116,9 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
116116
if (ret > 127)
117117
ret = 127;
118118

119+
cleanup:
120+
for (i = 0; i < 3; i++)
121+
free(mmfs[i].ptr);
122+
119123
return ret;
120124
}

builtin/pull.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
990990
int rebase_unspecified = 0;
991991
int can_ff;
992992
int divergent;
993+
int ret;
993994

994995
if (!getenv("GIT_REFLOG_ACTION"))
995996
set_reflog_message(argc, argv);
@@ -1100,7 +1101,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
11001101
if (is_null_oid(&orig_head)) {
11011102
if (merge_heads.nr > 1)
11021103
die(_("Cannot merge multiple branches into empty head."));
1103-
return pull_into_void(merge_heads.oid, &curr_head);
1104+
ret = pull_into_void(merge_heads.oid, &curr_head);
1105+
goto cleanup;
11041106
}
11051107
if (merge_heads.nr > 1) {
11061108
if (opt_rebase)
@@ -1125,8 +1127,6 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
11251127
}
11261128

11271129
if (opt_rebase) {
1128-
int ret = 0;
1129-
11301130
struct object_id newbase;
11311131
struct object_id upstream;
11321132
get_rebase_newbase_and_upstream(&newbase, &upstream, &curr_head,
@@ -1149,12 +1149,16 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
11491149
recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND))
11501150
ret = rebase_submodules();
11511151

1152-
return ret;
1152+
goto cleanup;
11531153
} else {
1154-
int ret = run_merge();
1154+
ret = run_merge();
11551155
if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON ||
11561156
recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND))
11571157
ret = update_submodules();
1158-
return ret;
1158+
goto cleanup;
11591159
}
1160+
1161+
cleanup:
1162+
oid_array_clear(&merge_heads);
1163+
return ret;
11601164
}

builtin/revert.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,9 @@ int cmd_revert(int argc, const char **argv, const char *prefix)
246246
res = run_sequencer(argc, argv, &opts);
247247
if (res < 0)
248248
die(_("revert failed"));
249+
if (opts.revs)
250+
release_revisions(opts.revs);
251+
free(opts.revs);
249252
return res;
250253
}
251254

submodule.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2388,7 +2388,7 @@ int get_superproject_working_tree(struct strbuf *buf)
23882388
struct child_process cp = CHILD_PROCESS_INIT;
23892389
struct strbuf sb = STRBUF_INIT;
23902390
struct strbuf one_up = STRBUF_INIT;
2391-
const char *cwd = xgetcwd();
2391+
char *cwd = xgetcwd();
23922392
int ret = 0;
23932393
const char *subpath;
23942394
int code;
@@ -2451,6 +2451,7 @@ int get_superproject_working_tree(struct strbuf *buf)
24512451
ret = 1;
24522452
free(super_wt);
24532453
}
2454+
free(cwd);
24542455
strbuf_release(&sb);
24552456

24562457
code = finish_command(&cp);

t/t0028-working-tree-encoding.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ test_description='working-tree-encoding conversion via gitattributes'
55
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
66
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
77

8+
TEST_PASSES_SANITIZE_LEAK=true
89
. ./test-lib.sh
910
. "$TEST_DIRECTORY/lib-encoding.sh"
1011

0 commit comments

Comments
 (0)