git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 1/7] t5326: demonstrate potential bitmap corruption

From
Taylor Blau <me@ttaylorr.com>
Date
Aug 22, 2022, 19:50 UTC
Message-ID
<6b38bfcd2c2bced350cea198f7d576ffb81f3481.1661197803.git.me@ttaylorr.com>
In-Reply-To
<cover.1661197803.git.me@ttaylorr.com>

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 <chakrabortyabhradeep79@gmail.com>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
 t/t5326-multi-pack-bitmaps.sh | 47 +++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh
index 4fe57414c1..c364677ae8 100755
--- a/t/t5326-multi-pack-bitmaps.sh
+++ b/t/t5326-multi-pack-bitmaps.sh
@@ -307,4 +307,51 @@ test_expect_success 'graceful fallback when missing reverse index' '
 	)
 '
 
+test_expect_success 'preferred pack change with existing MIDX bitmap' '
+	git init preferred-pack-with-existing &&
+	(
+		cd preferred-pack-with-existing &&
+
+		test_commit base &&
+		test_commit other &&
+
+		git rev-list --objects --no-object-names base >p1.objects &&
+		git rev-list --objects --no-object-names other >p2.objects &&
+
+		p1="$(git pack-objects "$objdir/pack/pack" \
+			--delta-base-offset <p1.objects)" &&
+		p2="$(git pack-objects "$objdir/pack/pack" \
+			--delta-base-offset <p2.objects)" &&
+
+		# Generate a MIDX containing the first two packs,
+		# marking p1 as preferred, and ensure that it can be
+		# successfully cloned.
+		git multi-pack-index write --bitmap \
+			--preferred-pack="pack-$p1.pack" &&
+		test_path_is_file $midx &&
+		test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
+		git clone --no-local . clone1 &&
+
+		# Then generate a new pack which sorts ahead of any
+		# existing pack (by tweaking the pack prefix).
+		test_commit foo &&
+		git pack-objects --all --unpacked $objdir/pack/pack0 &&
+
+		# Generate a new MIDX which changes the preferred pack
+		# to a pack contained in the existing MIDX, such that
+		# not all objects from p2 that appear in the MIDX had
+		# their copy selected from p2.
+		git multi-pack-index write --bitmap \
+			--preferred-pack="pack-$p2.pack" &&
+		test_path_is_file $midx &&
+		test_path_is_file $midx-$(midx_checksum $objdir).bitmap &&
+
+		# When the above circumstances are met, an existing bug
+		# in the MIDX machinery will cause the reverse index to
+		# be read incorrectly, resulting in failed clones (among
+		# other things).
+		test_must_fail git clone --no-local . clone2
+	)
+'
+
 test_done
-- 
2.37.0.1.g1379af2e9d
Previous: Taylor BlauNext: Taylor Blau
Message 21 of 29 in “midx: permit changing the preferred pack when reusing the MIDX”
  1. 0/6 midx: permit changing the preferred pack when reusing the MIDXTaylor Blau, Aug 19, 2022
  2. 1/6 t5326: demonstrate potential bitmap corruptionTaylor Blau, Aug 19, 2022
  3. Derrick StoleeAug 22, 2022
  4. Taylor BlauAug 22, 2022
  5. Junio C HamanoAug 22, 2022
  6. Taylor BlauAug 22, 2022
  7. 2/6 t/lib-bitmap.sh: avoid silencing stderrTaylor Blau, Aug 19, 2022
  8. Abhradeep ChakrabortyAug 20, 2022
  9. Taylor BlauAug 22, 2022
  10. 3/6 midx.c: extract `struct midx_fanout`Taylor Blau, Aug 19, 2022
  11. 4/6 midx.c: extract `midx_fanout_add_midx_fanout()`Taylor Blau, Aug 19, 2022
  12. 5/6 midx.c: extract `midx_fanout_add_pack_fanout()`Taylor Blau, Aug 19, 2022
  13. 6/6 midx.c: include preferred pack correctly with existing MIDXTaylor Blau, Aug 19, 2022
  14. Abhradeep ChakrabortyAug 20, 2022
  15. Taylor BlauAug 22, 2022
  16. Derrick StoleeAug 22, 2022
  17. Taylor BlauAug 22, 2022
  18. Derrick StoleeAug 22, 2022
  19. Taylor BlauAug 22, 2022
  20. 0/7 midx: permit changing the preferred pack when reusing the MIDXTaylor Blau, Aug 22, 2022
  21. 1/7 t5326: demonstrate potential bitmap corruptionTaylor Blau, Aug 22, 2022
  22. 2/7 t/lib-bitmap.sh: avoid silencing stderrTaylor Blau, Aug 22, 2022
  23. 3/7 midx.c: extract `struct midx_fanout`Taylor Blau, Aug 22, 2022
  24. 4/7 midx.c: extract `midx_fanout_add_midx_fanout()`Taylor Blau, Aug 22, 2022
  25. 5/7 midx.c: extract `midx_fanout_add_pack_fanout()`Taylor Blau, Aug 22, 2022
  26. 7/7 midx.c: avoid adding preferred objects twiceTaylor Blau, Aug 22, 2022
  27. Derrick StoleeAug 23, 2022
  28. 6/7 midx.c: include preferred pack correctly with existing MIDXTaylor Blau, Aug 22, 2022
  29. Derrick StoleeAug 23, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.