Skip to content

Commit 65168c4

Browse files
ttaylorrgitster
authored andcommitted
t5326: demonstrate potential bitmap corruption
It is possible to generate a corrupt MIDX bitmap when certain conditions are met. This happens when the preferred pack "P" changes to one (say, "Q") that: - "Q" has objects included in an existing MIDX, - but "Q" is different than "P", - and "Q" and "P" have some objects in common When this is the case, not all objects from "Q" will be selected from "Q" (ie., the generated MIDX will represent them as coming from a different pack), despite "Q" being preferred. This is an invariant violation, since all objects contained in the MIDX's preferred pack are supposed to originate from the preferred pack. In other words, all duplicate objects are resolved in favor of the copy that comes from the MIDX's preferred pack, if any. This violation results in a corrupt object order, which cannot be interpreted by the pack-bitmap code, leading to broken clones and other defects. This test demonstrates the above problem by constructing a minimal reproduction, and showing that the final `git clone` invocation fails. The reproduction is mostly straightforward, except that the new pack generated between MIDX writes (which is necessary in order to prevent that operation from being a noop) must sort ahead of all existing packs in order to prevent a different pack (neither "P" nor "Q") from appearing as preferred (meaning all its objects appear in order at the beginning of the pseudo-pack order). Subsequent commits will first refactor the midx.c::get_sorted_entries() function, and then fix this bug. Reported-by: Abhradeep Chakraborty <[email protected]> Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ad60ddd commit 65168c4

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

t/t5326-multi-pack-bitmaps.sh

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,4 +307,51 @@ test_expect_success 'graceful fallback when missing reverse index' '
307307
)
308308
'
309309

310+
test_expect_success 'preferred pack change with existing MIDX bitmap' '
311+
git init preferred-pack-with-existing &&
312+
(
313+
cd preferred-pack-with-existing &&
314+
315+
test_commit base &&
316+
test_commit other &&
317+
318+
git rev-list --objects --no-object-names base >p1.objects &&
319+
git rev-list --objects --no-object-names other >p2.objects &&
320+
321+
p1="$(git pack-objects "$objdir/pack/pack" \
322+
--delta-base-offset <p1.objects)" &&
323+
p2="$(git pack-objects "$objdir/pack/pack" \
324+
--delta-base-offset <p2.objects)" &&
325+
326+
# Generate a MIDX containing the first two packs,
327+
# marking p1 as preferred, and ensure that it can be
328+
# successfully cloned.
329+
git multi-pack-index write --bitmap \
330+
--preferred-pack="pack-$p1.pack" &&
331+
test_path_is_file $midx &&
332+
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
333+
git clone --no-local . clone1 &&
334+
335+
# Then generate a new pack which sorts ahead of any
336+
# existing pack (by tweaking the pack prefix).
337+
test_commit foo &&
338+
git pack-objects --all --unpacked $objdir/pack/pack0 &&
339+
340+
# Generate a new MIDX which changes the preferred pack
341+
# to a pack contained in the existing MIDX, such that
342+
# not all objects from p2 that appear in the MIDX had
343+
# their copy selected from p2.
344+
git multi-pack-index write --bitmap \
345+
--preferred-pack="pack-$p2.pack" &&
346+
test_path_is_file $midx &&
347+
test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
348+
349+
# When the above circumstances are met, an existing bug
350+
# in the MIDX machinery will cause the reverse index to
351+
# be read incorrectly, resulting in failed clones (among
352+
# other things).
353+
test_must_fail git clone --no-local . clone2
354+
)
355+
'
356+
310357
test_done

0 commit comments

Comments
 (0)