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:
parent
f0d2f84919
commit
4f33a6345f
2
bundle.c
2
bundle.c
@ -544,6 +544,8 @@ int create_bundle(struct repository *r, const char *path,
|
||||
die("revision walk setup failed");
|
||||
bpi.fd = bundle_fd;
|
||||
bpi.pending = &revs_copy.pending;
|
||||
|
||||
revs.blob_objects = revs.tree_objects = 0;
|
||||
traverse_commit_list(&revs, write_bundle_prerequisites, NULL, &bpi);
|
||||
object_array_remove_duplicates(&revs_copy.pending);
|
||||
|
||||
|
@ -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)
|
||||
/*
|
||||
|
@ -475,4 +475,16 @@ test_expect_success 'clone from bundle' '
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'unfiltered bundle with --objects' '
|
||||
git bundle create all-objects.bdl \
|
||||
--all --objects &&
|
||||
git bundle create all.bdl \
|
||||
--all &&
|
||||
|
||||
# Compare the headers of these files.
|
||||
sed -n -e "/^$/q" -e "p" all.bdl >expect &&
|
||||
sed -n -e "/^$/q" -e "p" all-objects.bdl >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
Loading…
Reference in New Issue
Block a user