Skip to content

Commit f87c55c

Browse files
pks-tgitster
authored andcommitted
object-name: free leaking object contexts
While it is documented in `struct object_context::path` that this variable needs to be released by the caller, this fact is rather easy to miss given that we do not ever provide a function to release the object context. And of course, while some callers dutifully release the path, many others don't. Introduce a new `object_context_release()` function that releases the path. Convert callsites that used to free the path to use that new function and add missing calls to callsites that were leaking memory. Refactor those callsites as required to have a single return path, only. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 61f8bb1 commit f87c55c

11 files changed

+97
-47
lines changed

builtin/cat-file.c

+11-6
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
102102
enum object_type type;
103103
char *buf;
104104
unsigned long size;
105-
struct object_context obj_context;
105+
struct object_context obj_context = {0};
106106
struct object_info oi = OBJECT_INFO_INIT;
107107
struct strbuf sb = STRBUF_INIT;
108108
unsigned flags = OBJECT_INFO_LOOKUP_REPLACE;
@@ -163,7 +163,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
163163
goto cleanup;
164164

165165
case 'e':
166-
return !repo_has_object_file(the_repository, &oid);
166+
ret = !repo_has_object_file(the_repository, &oid);
167+
goto cleanup;
167168

168169
case 'w':
169170

@@ -268,7 +269,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
268269
ret = 0;
269270
cleanup:
270271
free(buf);
271-
free(obj_context.path);
272+
object_context_release(&obj_context);
272273
return ret;
273274
}
274275

@@ -520,7 +521,7 @@ static void batch_one_object(const char *obj_name,
520521
struct batch_options *opt,
521522
struct expand_data *data)
522523
{
523-
struct object_context ctx;
524+
struct object_context ctx = {0};
524525
int flags =
525526
GET_OID_HASH_ANY |
526527
(opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0);
@@ -557,18 +558,22 @@ static void batch_one_object(const char *obj_name,
557558
break;
558559
}
559560
fflush(stdout);
560-
return;
561+
562+
goto out;
561563
}
562564

563565
if (ctx.mode == 0) {
564566
printf("symlink %"PRIuMAX"%c%s%c",
565567
(uintmax_t)ctx.symlink_path.len,
566568
opt->output_delim, ctx.symlink_path.buf, opt->output_delim);
567569
fflush(stdout);
568-
return;
570+
goto out;
569571
}
570572

571573
batch_object_write(obj_name, scratch, opt, data, NULL, 0);
574+
575+
out:
576+
object_context_release(&ctx);
572577
}
573578

574579
struct object_cb_data {

builtin/grep.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1114,7 +1114,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
11141114
for (i = 0; i < argc; i++) {
11151115
const char *arg = argv[i];
11161116
struct object_id oid;
1117-
struct object_context oc;
1117+
struct object_context oc = {0};
11181118
struct object *object;
11191119

11201120
if (!strcmp(arg, "--")) {
@@ -1140,7 +1140,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
11401140
if (!seen_dashdash)
11411141
verify_non_filename(prefix, arg);
11421142
add_object_array_with_path(object, arg, &list, oc.mode, oc.path);
1143-
free(oc.path);
1143+
object_context_release(&oc);
11441144
}
11451145

11461146
/*

builtin/log.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ static void show_tagger(const char *buf, struct rev_info *rev)
682682
static int show_blob_object(const struct object_id *oid, struct rev_info *rev, const char *obj_name)
683683
{
684684
struct object_id oidc;
685-
struct object_context obj_context;
685+
struct object_context obj_context = {0};
686686
char *buf;
687687
unsigned long size;
688688

@@ -698,15 +698,15 @@ static int show_blob_object(const struct object_id *oid, struct rev_info *rev, c
698698
if (!obj_context.path ||
699699
!textconv_object(the_repository, obj_context.path,
700700
obj_context.mode, &oidc, 1, &buf, &size)) {
701-
free(obj_context.path);
701+
object_context_release(&obj_context);
702702
return stream_blob_to_fd(1, oid, NULL, 0);
703703
}
704704

705705
if (!buf)
706706
die(_("git show %s: bad file"), obj_name);
707707

708708
write_or_die(1, buf, size);
709-
free(obj_context.path);
709+
object_context_release(&obj_context);
710710
return 0;
711711
}
712712

builtin/ls-tree.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
367367
OPT_END()
368368
};
369369
struct ls_tree_cmdmode_to_fmt *m2f = ls_tree_cmdmode_format;
370-
struct object_context obj_context;
370+
struct object_context obj_context = {0};
371371
int ret;
372372

373373
git_config(git_default_config, NULL);
@@ -441,5 +441,6 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
441441

442442
ret = !!read_tree(the_repository, tree, &options.pathspec, fn, &options);
443443
clear_pathspec(&options.pathspec);
444+
object_context_release(&obj_context);
444445
return ret;
445446
}

builtin/rev-parse.c

+2
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
11281128
}
11291129
if (!get_oid_with_context(the_repository, name,
11301130
flags, &oid, &unused)) {
1131+
object_context_release(&unused);
11311132
if (output_algo)
11321133
repo_oid_to_algop(the_repository, &oid,
11331134
output_algo, &oid);
@@ -1137,6 +1138,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
11371138
show_rev(type, &oid, name);
11381139
continue;
11391140
}
1141+
object_context_release(&unused);
11401142
if (verify)
11411143
die_no_single_rev(quiet);
11421144
if (has_dashdash)

builtin/stash.c

+9-3
Original file line numberDiff line numberDiff line change
@@ -1018,13 +1018,14 @@ static int store_stash(int argc, const char **argv, const char *prefix)
10181018
int quiet = 0;
10191019
const char *stash_msg = NULL;
10201020
struct object_id obj;
1021-
struct object_context dummy;
1021+
struct object_context dummy = {0};
10221022
struct option options[] = {
10231023
OPT__QUIET(&quiet, N_("be quiet")),
10241024
OPT_STRING('m', "message", &stash_msg, "message",
10251025
N_("stash message")),
10261026
OPT_END()
10271027
};
1028+
int ret;
10281029

10291030
argc = parse_options(argc, argv, prefix, options,
10301031
git_stash_store_usage,
@@ -1043,10 +1044,15 @@ static int store_stash(int argc, const char **argv, const char *prefix)
10431044
if (!quiet)
10441045
fprintf_ln(stderr, _("Cannot update %s with %s"),
10451046
ref_stash, argv[0]);
1046-
return -1;
1047+
ret = -1;
1048+
goto out;
10471049
}
10481050

1049-
return do_store_stash(&obj, stash_msg, quiet);
1051+
ret = do_store_stash(&obj, stash_msg, quiet);
1052+
1053+
out:
1054+
object_context_release(&dummy);
1055+
return ret;
10501056
}
10511057

10521058
static void add_pathspecs(struct strvec *args,

list-objects-filter.c

+2
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,8 @@ static void filter_sparse_oid__init(
542542
filter->filter_data = d;
543543
filter->filter_object_fn = filter_sparse;
544544
filter->free_fn = filter_sparse_free;
545+
546+
object_context_release(&oc);
545547
}
546548

547549
/*

object-name.c

+29-11
Original file line numberDiff line numberDiff line change
@@ -1757,14 +1757,21 @@ int strbuf_check_branch_ref(struct strbuf *sb, const char *name)
17571757
return check_refname_format(sb->buf, 0);
17581758
}
17591759

1760+
void object_context_release(struct object_context *ctx)
1761+
{
1762+
free(ctx->path);
1763+
}
1764+
17601765
/*
17611766
* This is like "get_oid_basic()", except it allows "object ID expressions",
17621767
* notably "xyz^" for "parent of xyz"
17631768
*/
17641769
int repo_get_oid(struct repository *r, const char *name, struct object_id *oid)
17651770
{
17661771
struct object_context unused;
1767-
return get_oid_with_context(r, name, 0, oid, &unused);
1772+
int ret = get_oid_with_context(r, name, 0, oid, &unused);
1773+
object_context_release(&unused);
1774+
return ret;
17681775
}
17691776

17701777
/*
@@ -1802,44 +1809,54 @@ int repo_get_oid_committish(struct repository *r,
18021809
struct object_id *oid)
18031810
{
18041811
struct object_context unused;
1805-
return get_oid_with_context(r, name, GET_OID_COMMITTISH,
1806-
oid, &unused);
1812+
int ret = get_oid_with_context(r, name, GET_OID_COMMITTISH,
1813+
oid, &unused);
1814+
object_context_release(&unused);
1815+
return ret;
18071816
}
18081817

18091818
int repo_get_oid_treeish(struct repository *r,
18101819
const char *name,
18111820
struct object_id *oid)
18121821
{
18131822
struct object_context unused;
1814-
return get_oid_with_context(r, name, GET_OID_TREEISH,
1815-
oid, &unused);
1823+
int ret = get_oid_with_context(r, name, GET_OID_TREEISH,
1824+
oid, &unused);
1825+
object_context_release(&unused);
1826+
return ret;
18161827
}
18171828

18181829
int repo_get_oid_commit(struct repository *r,
18191830
const char *name,
18201831
struct object_id *oid)
18211832
{
18221833
struct object_context unused;
1823-
return get_oid_with_context(r, name, GET_OID_COMMIT,
1824-
oid, &unused);
1834+
int ret = get_oid_with_context(r, name, GET_OID_COMMIT,
1835+
oid, &unused);
1836+
object_context_release(&unused);
1837+
return ret;
18251838
}
18261839

18271840
int repo_get_oid_tree(struct repository *r,
18281841
const char *name,
18291842
struct object_id *oid)
18301843
{
18311844
struct object_context unused;
1832-
return get_oid_with_context(r, name, GET_OID_TREE,
1833-
oid, &unused);
1845+
int ret = get_oid_with_context(r, name, GET_OID_TREE,
1846+
oid, &unused);
1847+
object_context_release(&unused);
1848+
return ret;
18341849
}
18351850

18361851
int repo_get_oid_blob(struct repository *r,
18371852
const char *name,
18381853
struct object_id *oid)
18391854
{
18401855
struct object_context unused;
1841-
return get_oid_with_context(r, name, GET_OID_BLOB,
1842-
oid, &unused);
1856+
int ret = get_oid_with_context(r, name, GET_OID_BLOB,
1857+
oid, &unused);
1858+
object_context_release(&unused);
1859+
return ret;
18431860
}
18441861

18451862
/* Must be called only when object_name:filename doesn't exist. */
@@ -2117,6 +2134,7 @@ void maybe_die_on_misspelt_object_name(struct repository *r,
21172134
struct object_id oid;
21182135
get_oid_with_context_1(r, name, GET_OID_ONLY_TO_DIE | GET_OID_QUIETLY,
21192136
prefix, &oid, &oc);
2137+
object_context_release(&oc);
21202138
}
21212139

21222140
enum get_oid_result get_oid_with_context(struct repository *repo,

object-name.h

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ struct object_context {
2222
char *path;
2323
};
2424

25+
void object_context_release(struct object_context *ctx);
26+
2527
/*
2628
* Return an abbreviated sha1 unique within this repository's object database.
2729
* The result will be at least `len` characters long, and will be NUL

0 commit comments

Comments
 (0)