Skip to content

Commit d3b6f6c

Browse files
peffgitster
authored andcommitted
commit-graph: use fanout value for graph size
Commit-graph, midx, and pack idx files all have both a lookup table of oids and an oid fanout table. In midx and pack idx files, we take the final entry of the fanout table as the source of truth for the number of entries, and then verify that the size of the lookup table matches that. But for commit-graph files, we do the opposite: we use the size of the lookup table as the source of truth, and then check the final fanout entry against it. As noted in 4169d89 (commit-graph: check consistency of fanout table, 2023-10-09), either is correct. But there are a few reasons to prefer the fanout table as the source of truth: 1. The fanout entries are 32-bits on disk, and that defines the maximum number of entries we can store. But since the size of the lookup table is only bounded by the filesystem, it can be much larger. And hence computing it as the commit-graph does means that we may truncate the result when storing it in a uint32_t. 2. We read the fanout first, then the lookup table. If we're verifying the chunks as we read them, then we'd want to take the fanout as truth (we have nothing yet to check it against) and then we can check that the lookup table matches what we already know. 3. It is pointlessly inconsistent with the midx and pack idx code. Since the three have to do similar size and bounds checks, it is easier to reason about all three if they use the same approach. So this patch moves the assignment of g->num_commits to the fanout parser, and then we can check the size of the lookup chunk as soon as we try to load it. There's already a test covering this situation, which munges the final fanout entry to 2^32-1. In the current code we complain that it does not agree with the table size. But now that we treat the munged value as the source of truth, we'll complain that the lookup table is the wrong size (again, either is correct). So we'll have to update the message we expect (and likewise for an earlier test which does similar munging). There's a similar test for this situation on the midx side, but rather than making a very-large fanout value, it just truncates the lookup table. We could do that here, too, but the very-large fanout value actually shows an interesting corner case. On a 32-bit system, multiplying to find the expected table size would cause an integer overflow. Using st_mult() would detect that, but cause us to die() rather than falling back to the non-graph code path. Checking the size using division (as we do with existing chunk-size checks) avoids the overflow entirely, and the test demonstrates this when run on a 32-bit system. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8bd40ed commit d3b6f6c

File tree

2 files changed

+6
-7
lines changed

2 files changed

+6
-7
lines changed

commit-graph.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,6 @@ static int verify_commit_graph_lite(struct commit_graph *g)
300300
return 1;
301301
}
302302
}
303-
if (ntohl(g->chunk_oid_fanout[255]) != g->num_commits) {
304-
error("commit-graph oid table and fanout disagree on size");
305-
return 1;
306-
}
307303

308304
return 0;
309305
}
@@ -315,6 +311,7 @@ static int graph_read_oid_fanout(const unsigned char *chunk_start,
315311
if (chunk_size != 256 * sizeof(uint32_t))
316312
return error("commit-graph oid fanout chunk is wrong size");
317313
g->chunk_oid_fanout = (const uint32_t *)chunk_start;
314+
g->num_commits = ntohl(g->chunk_oid_fanout[255]);
318315
return 0;
319316
}
320317

@@ -323,7 +320,8 @@ static int graph_read_oid_lookup(const unsigned char *chunk_start,
323320
{
324321
struct commit_graph *g = data;
325322
g->chunk_oid_lookup = chunk_start;
326-
g->num_commits = chunk_size / g->hash_len;
323+
if (chunk_size / g->hash_len != g->num_commits)
324+
return error(_("commit-graph OID lookup chunk is the wrong size"));
327325
return 0;
328326
}
329327

t/t5318-commit-graph.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ test_expect_success 'detect incorrect fanout' '
560560

561561
test_expect_success 'detect incorrect fanout final value' '
562562
corrupt_graph_and_verify $GRAPH_BYTE_FANOUT2 "\01" \
563-
"oid table and fanout disagree on size"
563+
"OID lookup chunk is the wrong size"
564564
'
565565

566566
test_expect_success 'detect incorrect OID order' '
@@ -850,7 +850,8 @@ test_expect_success 'reader notices too-small oid fanout chunk' '
850850
test_expect_success 'reader notices fanout/lookup table mismatch' '
851851
check_corrupt_chunk OIDF 1020 "FFFFFFFF" &&
852852
cat >expect.err <<-\EOF &&
853-
error: commit-graph oid table and fanout disagree on size
853+
error: commit-graph OID lookup chunk is the wrong size
854+
error: commit-graph required OID lookup chunk missing or corrupted
854855
EOF
855856
test_cmp expect.err err
856857
'

0 commit comments

Comments
 (0)