list-objects: handle NULL function pointers

If a caller to traverse_commit_list() specifies the options for the
--objects flag but does not specify a show_object function pointer, the
result is a segfault. This is currently visible by running 'git bundle
create --objects HEAD'.

We could fix this problem by supplying a no-op callback in
builtin/bundle.c, but that only solves the problem for one builtin,
leaving this segfault open for other callers.

Replace all callers of the show_commit and show_object function pointers
in list-objects.c to call helper functions show_commit() and
show_object() which check that the given context has non-NULL functions
before passing the necessary data. One extra benefit is that it reduces
duplication due to passing ctx->show_data to every caller.

Test that this segfault no longer occurs for 'git bundle'.

Co-authored-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Ævar Arnfjörð Bjarmason
2022-03-09 16:01:38 +00:00
committed by Junio C Hamano
parent f0d2f84919
commit 4f33a6345f
3 changed files with 36 additions and 5 deletions

View File

@ -21,6 +21,23 @@ struct traversal_context {
struct filter *filter;
};
static void show_commit(struct traversal_context *ctx,
struct commit *commit)
{
if (!ctx->show_commit)
return;
ctx->show_commit(commit, ctx->show_data);
}
static void show_object(struct traversal_context *ctx,
struct object *object,
const char *name)
{
if (!ctx->show_object)
return;
ctx->show_object(object, name, ctx->show_data);
}
static void process_blob(struct traversal_context *ctx,
struct blob *blob,
struct strbuf *path,
@ -60,7 +77,7 @@ static void process_blob(struct traversal_context *ctx,
if (r & LOFR_MARK_SEEN)
obj->flags |= SEEN;
if (r & LOFR_DO_SHOW)
ctx->show_object(obj, path->buf, ctx->show_data);
show_object(ctx, obj, path->buf);
strbuf_setlen(path, pathlen);
}
@ -194,7 +211,7 @@ static void process_tree(struct traversal_context *ctx,
if (r & LOFR_MARK_SEEN)
obj->flags |= SEEN;
if (r & LOFR_DO_SHOW)
ctx->show_object(obj, base->buf, ctx->show_data);
show_object(ctx, obj, base->buf);
if (base->len)
strbuf_addch(base, '/');
@ -210,7 +227,7 @@ static void process_tree(struct traversal_context *ctx,
if (r & LOFR_MARK_SEEN)
obj->flags |= SEEN;
if (r & LOFR_DO_SHOW)
ctx->show_object(obj, base->buf, ctx->show_data);
show_object(ctx, obj, base->buf);
strbuf_setlen(base, baselen);
free_tree_buffer(tree);
@ -228,7 +245,7 @@ static void process_tag(struct traversal_context *ctx,
if (r & LOFR_MARK_SEEN)
tag->object.flags |= SEEN;
if (r & LOFR_DO_SHOW)
ctx->show_object(&tag->object, name, ctx->show_data);
show_object(ctx, &tag->object, name);
}
static void mark_edge_parents_uninteresting(struct commit *commit,
@ -402,7 +419,7 @@ static void do_traverse(struct traversal_context *ctx)
if (r & LOFR_MARK_SEEN)
commit->object.flags |= SEEN;
if (r & LOFR_DO_SHOW)
ctx->show_commit(commit, ctx->show_data);
show_commit(ctx, commit);
if (ctx->revs->tree_blobs_in_commit_order)
/*