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

[PATCH 21/20] t5319: make corrupted large-offset test more robust

From
Jeff King <peff@peff.net>
Date
Oct 14, 2023, 00:43 UTC
Message-ID
<20231014004348.GA43880@coredump.intra.peff.net>
In-Reply-To
<20231009205544.GA3281950@coredump.intra.peff.net>
On Mon, Oct 09, 2023 at 04:55:44PM -0400, Jeff King wrote:
>   [10/20]: midx: bounds-check large offset chunk

Here's one more patch on top that fixes a flaky test. Sorry not to have caught it before sending out the original series. I did see a flaky CI run before then, but I tweaked the test with what I thought was the solution, and then it didn't re-occur until I ran CI again today.

I'm pretty sure this should fix it for good.

(I also saw Taylor posted some further patches; I haven't looked closely yet, this should be orthogonal to those).

-- >8 --
Subject: [PATCH] t5319: make corrupted large-offset test more robust

The test t5319.88 ("reader bounds-checks large offset table") can fail intermittently. The failure mode looks like this:

  1. An earlier test sets up "objects64", a directory that can be used
     to produce a midx with a corrupted large-offsets table. To get the
     large offsets, it corrupts the normal ".idx" file to have a fake
     large offset, and then builds a midx from that.
     That midx now has a large offset table, which is what we want. But
     we also have a .idx on disk that has a corrupted entry. We'll call
     the object with the corrupted large-offset "X".
  2. In t5319.88, we further corrupt the midx by reducing the size of
     the large-offset chunk (because our goal is to make sure we do not
     do an out-of-bounds read on it).
  3. We then enumerate all of the objects with "cat-file --batch-check
     --batch-all-objects", expecting to see a complaint when we try to
     show object X. We use --batch-all-objects because our objects64
     repo doesn't actually have any refs (but if we check them all, one
     of them will be the failing one). The default batch-check format
     includes %(objecttype) and %(objectsize), both of which require us
     to access the actual pack data (and thus requires looking at the
     offset).
  4a. Usually, this succeeds. We try to output object X, do a lookup via
      the midx for the type/size lookup, and run into the corrupt
      large-offset table.
  4b. But sometimes we hit a different error. If another object points
      to X as a delta base, then trying to find the type of that object
      requires walking the delta chain to the base entry (since only the
      base has the concrete type; deltas themselves are either OFS_DELTA
      or REF_DELTA).
      Normally this would not require separate offset lookups at all, as
      deltas are usually stored as OFS_DELTA, specifying the relative
      offset to the base. But the corrupt idx created in step 1 is done
      directly with "git pack-objects" and does not pass the
      --delta-base-offset option, meaning we have REF_DELTA entries!
      Those do have to consult an index to find the location of the base
      object, and they use the pack .idx to do this. The same pack .idx
      that we know is corrupted from step 1!
      Git does notice the error, but it does so by seeing the corrupt
      .idx file, not the corrupt midx file, and the error it reports is
      different, causing the test to fail.

The set of objects created in the test is deterministic. But the delta selection seems not to be (which is not too surprising, as it is multi-threaded). I have seen the failure in Windows CI but haven't reproduced it locally (not even with --stress). Re-running a failed Windows CI job tends to work. But when I download and examine the trash directory from a failed run, it shows a different set of deltas than I get locally. But the exact source of non-determinism isn't that important; our test should be robust against any order.

There are a few options to fix this:
  a. It would be OK for the "objects64" setup to "unbreak" the .idx file
     after generating the midx. But then it would be hard for subsequent
     tests to reuse it, since it is the corrupted idx that forces the
     midx to have a large offset table.
  b. The "objects64" setup could use --delta-base-offset. This would fix
     our problem, but earlier tests have many hard-coded offsets. Using
     OFS_DELTA would change the locations of objects in the pack (this
     might even be OK because I think most of the offsets are within the
     .idx file, but it seems brittle and I'm afraid to touch it).
  c. Our cat-file output is in oid order by default. Since we store
     bases before deltas, if we went in pack order (using the
     "--unordered" flag), we'd always see our corrupt X before any delta
     which depends on it. But using "--unordered" means we skip the midx
     entirely. That makes sense, since it is just enumerating all of
     the packs, using the offsets found in their .idx files directly.
     So it doesn't work for our test.
  d. We could ask directly about object X, rather than enumerating all
     of them. But that requires further hard-coding of the oid (both
     sha1 and sha256) of object X. I'd prefer not to introduce more
     brittleness.
  e. We can use a --batch-check format that looks at the pack data, but
     doesn't have to chase deltas. The problem in this case is
     %(objecttype), which has to walk to the base. But %(objectsize)
     does not; we can get the value directly from the delta itself.
     Another option would be %(deltabase), where we report the REF_DELTA
     name but don't look at its data.

I've gone with option (e) here. It's kind of subtle, but it's simple and has no side effects.

Signed-off-by: Jeff King <peff@peff.net>
---
 t/t5319-multi-pack-index.sh | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index 2a11dd1af6..d3c9e97feb 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -1129,8 +1129,10 @@ test_expect_success 'reader bounds-checks large offset table' '
 		git multi-pack-index --object-dir=../objects64 write &&
 		midx=../objects64/pack/multi-pack-index &&
 		corrupt_chunk_file $midx LOFF clear &&
-		test_must_fail git cat-file \
-			--batch-check --batch-all-objects 2>err &&
+		# using only %(objectsize) is important here; see the commit
+		# message for more details
+		test_must_fail git cat-file --batch-all-objects \
+			--batch-check="%(objectsize)" 2>err &&
 		cat >expect <<-\EOF &&
 		fatal: multi-pack-index large offset out of bounds
 		EOF
-- 
2.42.0.937.g4d9eb42d36
Previous: Jeff KingNext: Junio C Hamano
Message 64 of 67 in “bounds-checks for chunk-based files”
  1. 0/20 bounds-checks for chunk-based filesJeff King, Oct 9, 2023
  2. 01/20 chunk-format: note that pair_chunk() is unsafeJeff King, Oct 9, 2023
  3. Taylor BlauOct 10, 2023
  4. Jeff KingOct 11, 2023
  5. 02/20 t: add library for munging chunk-format filesJeff King, Oct 9, 2023
  6. Taylor BlauOct 10, 2023
  7. 03/20 midx: stop ignoring malformed oid fanout chunkJeff King, Oct 9, 2023
  8. Taylor BlauOct 10, 2023
  9. Jeff KingOct 11, 2023
  10. 04/20 commit-graph: check size of oid fanout chunkJeff King, Oct 9, 2023
  11. Taylor BlauOct 11, 2023
  12. Taylor BlauOct 11, 2023
  13. Jeff KingOct 11, 2023
  14. 05/20 midx: check size of oid lookup chunkJeff King, Oct 9, 2023
  15. 06/20 commit-graph: check consistency of fanout tableJeff King, Oct 9, 2023
  16. Taylor BlauOct 11, 2023
  17. 07/20 midx: check size of pack names chunkJeff King, Oct 9, 2023
  18. Taylor BlauOct 11, 2023
  19. Jeff KingOct 11, 2023
  20. 08/20 midx: enforce chunk alignment on readingJeff King, Oct 9, 2023
  21. Taylor BlauOct 11, 2023
  22. Taylor BlauOct 11, 2023
  23. Jeff KingOct 11, 2023
  24. 09/20 midx: check size of object offset chunkJeff King, Oct 9, 2023
  25. Taylor BlauOct 11, 2023
  26. 10/20 midx: bounds-check large offset chunkJeff King, Oct 9, 2023
  27. Taylor BlauOct 11, 2023
  28. Jeff KingOct 11, 2023
  29. 11/20 midx: check size of revindex chunkJeff King, Oct 9, 2023
  30. Taylor BlauOct 11, 2023
  31. 12/20 commit-graph: check size of commit data chunkJeff King, Oct 9, 2023
  32. Taylor BlauOct 11, 2023
  33. Jeff KingOct 11, 2023
  34. 13/20 commit-graph: detect out-of-bounds extra-edges pointersJeff King, Oct 9, 2023
  35. Taylor BlauOct 11, 2023
  36. 14/20 commit-graph: bounds-check base graphs chunkJeff King, Oct 9, 2023
  37. Taylor BlauOct 11, 2023
  38. 15/20 commit-graph: check size of generations chunkJeff King, Oct 9, 2023
  39. 16/20 commit-graph: bounds-check generation overflow chunkJeff King, Oct 9, 2023
  40. 17/20 commit-graph: check bounds when accessing BDAT chunkJeff King, Oct 9, 2023
  41. Taylor BlauOct 11, 2023
  42. Jeff KingOct 11, 2023
  43. 18/20 commit-graph: check bounds when accessing BIDX chunkJeff King, Oct 9, 2023
  44. Taylor BlauOct 11, 2023
  45. 19/20 commit-graph: detect out-of-order BIDX offsetsJeff King, Oct 9, 2023
  46. Taylor BlauOct 11, 2023
  47. 20/20 chunk-format: drop pair_chunk_unsafe()Jeff King, Oct 9, 2023
  48. Taylor BlauOct 11, 2023
  49. Jeff KingOct 11, 2023
  50. 0/8 chunk-format: introduce `pair_chunk_expect()` convenience APITaylor Blau, Oct 13, 2023
  51. 1/8 chunk-format: introduce `pair_chunk_expect()` helperTaylor Blau, Oct 13, 2023
  52. 2/8 commit-graph: read `OIDF` chunk with `pair_chunk_expect()`Taylor Blau, Oct 13, 2023
  53. 3/8 commit-graph: read `CDAT` chunk with `pair_chunk_expect()`Taylor Blau, Oct 13, 2023
  54. 4/8 commit-graph: read `GDAT` chunk with `pair_chunk_expect()`Taylor Blau, Oct 13, 2023
  55. 5/8 commit-graph: read `BIDX` chunk with `pair_chunk_expect()`Taylor Blau, Oct 13, 2023
  56. Taylor BlauOct 13, 2023
  57. Junio C HamanoOct 14, 2023
  58. Jeff KingOct 20, 2023
  59. 6/8 midx: read `OIDF` chunk with `pair_chunk_expect()`Taylor Blau, Oct 13, 2023
  60. Junio C HamanoOct 13, 2023
  61. 7/8 midx: read `OIDL` chunk with `pair_chunk_expect()`Taylor Blau, Oct 13, 2023
  62. 8/8 midx: read `OOFF` chunk with `pair_chunk_expect()`Taylor Blau, Oct 13, 2023
  63. Jeff KingOct 20, 2023
  64. 21/20 t5319: make corrupted large-offset test more robustJeff King, Oct 14, 2023
  65. Junio C HamanoOct 14, 2023
  66. Jeff KingOct 15, 2023
  67. Junio C HamanoOct 15, 2023

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.