Skip to content

Commit 692232b

Browse files
committed
midx-write: only load initialized packs
The fill_packs_from_midx() method was refactored in fcb2205 (midx: implement support for writing incremental MIDX chains, 2024-08-06) to allow for preferred packfiles and incremental multi-pack-indexes. However, this led to some conditions that can cause improperly initialized memory in the context's list of packfiles. The conditions caring about the preferred pack name or the incremental flag are currently necessary to load a packfile. But the context is still being populated with pack_info structs based on the packfile array for the existing multi-pack-index even if prepare_midx_pack() isn't called. I'm not sure how to reproduce this situation in a test case (and it would be great if I could) but some calls to the 'repack' or 'expire' subcommand of 'git multi-pack-index' could segfault later due to these improperly initialized pack_info structs. The current change does fix the large, real-world case that I had observed with a debugger. It is worth noting that there are test cases around the 'expire' subcommand that will fail if we attempt to open the pack index during this loop, or if we ignore packs that fail to open the pack index in this loop. The removal of the calls to open_pack_index() reverts back to the condition before this was refactored. The only instance where this mattered was a check to see if the preferred packfile had objects or not, so the initialization of the preferred pack was deferred to that place. To the best of my knowledge, the incremental feature does not require the pack-indexes to be opened during this process. Signed-off-by: Derrick Stolee <[email protected]>
1 parent aaa5949 commit 692232b

File tree

1 file changed

+8
-27
lines changed

1 file changed

+8
-27
lines changed

midx-write.c

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -945,39 +945,21 @@ static struct multi_pack_index *lookup_multi_pack_index(struct repository *r,
945945
return result;
946946
}
947947

948-
static int fill_packs_from_midx(struct write_midx_context *ctx,
949-
const char *preferred_pack_name, uint32_t flags)
948+
static int fill_packs_from_midx(struct write_midx_context *ctx)
950949
{
951950
struct multi_pack_index *m;
952951

953952
for (m = ctx->m; m; m = m->base_midx) {
954953
uint32_t i;
955954

956955
for (i = 0; i < m->num_packs; i++) {
957-
ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc);
958-
959-
/*
960-
* If generating a reverse index, need to have
961-
* packed_git's loaded to compare their
962-
* mtimes and object count.
963-
*
964-
* If a preferred pack is specified, need to
965-
* have packed_git's loaded to ensure the chosen
966-
* preferred pack has a non-zero object count.
967-
*/
968-
if (flags & MIDX_WRITE_REV_INDEX ||
969-
preferred_pack_name) {
970-
if (prepare_midx_pack(ctx->repo, m,
971-
m->num_packs_in_base + i)) {
972-
error(_("could not load pack"));
973-
return -1;
974-
}
975-
976-
if (open_pack_index(m->packs[i]))
977-
die(_("could not open index for %s"),
978-
m->packs[i]->pack_name);
956+
if (prepare_midx_pack(ctx->repo, m,
957+
m->num_packs_in_base + i)) {
958+
error(_("could not load pack"));
959+
return -1;
979960
}
980961

962+
ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc);
981963
fill_pack_info(&ctx->info[ctx->nr++], m->packs[i],
982964
m->pack_names[i],
983965
m->num_packs_in_base + i);
@@ -1149,8 +1131,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
11491131
ctx.num_multi_pack_indexes_before++;
11501132
m = m->base_midx;
11511133
}
1152-
} else if (ctx.m && fill_packs_from_midx(&ctx, preferred_pack_name,
1153-
flags) < 0) {
1134+
} else if (ctx.m && fill_packs_from_midx(&ctx) < 0) {
11541135
result = 1;
11551136
goto cleanup;
11561137
}
@@ -1251,7 +1232,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
12511232

12521233
if (ctx.preferred_pack_idx != NO_PREFERRED_PACK) {
12531234
struct packed_git *preferred = ctx.info[ctx.preferred_pack_idx].p;
1254-
if (!preferred->num_objects) {
1235+
if (open_pack_index(preferred) || !preferred->num_objects) {
12551236
error(_("cannot select preferred pack %s with no objects"),
12561237
preferred->pack_name);
12571238
result = 1;

0 commit comments

Comments
 (0)