midx: fix segfault with no packs and invalid preferred pack

When asked to write a multi-pack-index the user can specify a preferred pack that is used as a tie breaker when multiple packs contain the same objects. When this packfile cannot be found, we just pick the first pack that is getting tracked by the newly written multi-pack-index as a fallback. Picking the fallback can fail in the case where we're asked to write a multi-pack-index with no packfiles at all: picking the fallback value will cause a segfault as we blindly index into the array of packfiles, which would be empty. Fix this bug by resetting the preferred packfile index to `-1` before searching for the preferred pack. This fixes the segfault as we already check for whether the index is `> - 1`. If it is not, we simply don't pick a preferred packfile at all. Helped-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Apr 14, 2023 at 08:01 UTC ceb96a160b05c3ec45c416851bac00b711418839
2 files changed +15 -3
midx.c
+3 -3
@@ -1326,17 +1326,17 @@ static int write_midx_internal(const char *object_dir,
1326 }
1327
1328 if (preferred_pack_name) {
1329 - int found = 0;
1329 + ctx.preferred_pack_idx = -1;
1330 +
1331 for (i = 0; i < ctx.nr; i++) {
1332 if (!cmp_idx_or_pack_name(preferred_pack_name,
1333 ctx.info[i].pack_name)) {
1334 ctx.preferred_pack_idx = i;
1334 - found = 1;
1335 break;
1336 }
1337 }
1338
1339 - if (!found)
1339 + if (ctx.preferred_pack_idx == -1)
1340 warning(_("unknown preferred pack: '%s'"),
1341 preferred_pack_name);
1342 } else if (ctx.nr &&
t/t5319-multi-pack-index.sh
+12
@@ -183,6 +183,18 @@ test_expect_success 'write midx with --stdin-packs' '
183
184 compare_results_with_midx "mixed mode (one pack + extra)"
185
186 +test_expect_success 'write with no objects and preferred pack' '
187 + test_when_finished "rm -rf empty" &&
188 + git init empty &&
189 + test_must_fail git -C empty multi-pack-index write \
190 + --stdin-packs --preferred-pack=does-not-exist </dev/null 2>err &&
191 + cat >expect <<-EOF &&
192 + warning: unknown preferred pack: ${SQ}does-not-exist${SQ}
193 + error: no pack files to index.
194 + EOF
195 + test_cmp expect err
196 +'
197 +
198 test_expect_success 'write progress off for redirected stderr' '
199 git multi-pack-index --object-dir=$objdir write 2>err &&
200 test_line_count = 0 err