commit-graph: check order while reading fanout chunk

We read the fanout chunk, storing a pointer to it, but only confirm that the entries are monotonic in a final "lite" verification step. Let's move that into the actual OIDF chunk callback, so that we can report problems immediately (for all the reasons given in the previous "commit-graph: abort as soon as we see a bogus chunk" commit). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Nov 9, 2023 at 02:25 UTC 06fb135f8eddc64071a719fe309c771883c07775
2 files changed +14 -12
commit-graph.c
+13 -12
@@ -277,8 +277,6 @@ struct commit_graph *load_commit_graph_one_fd_st(struct repository *r,
277
278 static int verify_commit_graph_lite(struct commit_graph *g)
279 {
280 - int i;
281 -
280 /*
281 * Basic validation shared between parse_commit_graph()
282 * which'll be called every time the graph is used, and the
@@ -291,16 +289,6 @@ static int verify_commit_graph_lite(struct commit_graph *g)
289 * over g->num_commits, or runs a checksum on the commit-graph
290 * itself.
291 */
294 - for (i = 0; i < 255; i++) {
295 - uint32_t oid_fanout1 = ntohl(g->chunk_oid_fanout[i]);
296 - uint32_t oid_fanout2 = ntohl(g->chunk_oid_fanout[i + 1]);
297 -
298 - if (oid_fanout1 > oid_fanout2) {
299 - error("commit-graph fanout values out of order");
300 - return 1;
301 - }
302 - }
303 -
292 return 0;
293 }
294
@@ -308,10 +296,23 @@ static int graph_read_oid_fanout(const unsigned char *chunk_start,
296 size_t chunk_size, void *data)
297 {
298 struct commit_graph *g = data;
299 + int i;
300 +
301 if (chunk_size != 256 * sizeof(uint32_t))
302 return error("commit-graph oid fanout chunk is wrong size");
303 g->chunk_oid_fanout = (const uint32_t *)chunk_start;
304 g->num_commits = ntohl(g->chunk_oid_fanout[255]);
305 +
306 + for (i = 0; i < 255; i++) {
307 + uint32_t oid_fanout1 = ntohl(g->chunk_oid_fanout[i]);
308 + uint32_t oid_fanout2 = ntohl(g->chunk_oid_fanout[i + 1]);
309 +
310 + if (oid_fanout1 > oid_fanout2) {
311 + error("commit-graph fanout values out of order");
312 + return 1;
313 + }
314 + }
315 +
316 return 0;
317 }
318
t/t5318-commit-graph.sh
+1
@@ -867,6 +867,7 @@ test_expect_success 'reader notices out-of-bounds fanout' '
867 check_corrupt_chunk OIDF 0 $(printf "%02x000000" $(test_seq 0 254)) &&
868 cat >expect.err <<-\EOF &&
869 error: commit-graph fanout values out of order
870 + error: commit-graph required OID fanout chunk missing or corrupted
871 EOF
872 test_cmp expect.err err
873 '