diff --git a/chunk-format.c b/chunk-format.c index cdc7f39b70..be078dcca8 100644 --- a/chunk-format.c +++ b/chunk-format.c @@ -163,6 +163,10 @@ int read_table_of_contents(struct chunkfile *cf, struct pair_chunk_data { const unsigned char **p; size_t *size; + + /* for pair_chunk_expect() only */ + size_t record_size; + size_t record_nr; }; static int pair_chunk_fn(const unsigned char *chunk_start, @@ -175,6 +179,17 @@ static int pair_chunk_fn(const unsigned char *chunk_start, return 0; } +static int pair_chunk_expect_fn(const unsigned char *chunk_start, + size_t chunk_size, + void *data) +{ + struct pair_chunk_data *pcd = data; + if (chunk_size / pcd->record_size != pcd->record_nr) + return -1; + *pcd->p = chunk_start; + return 0; +} + int pair_chunk(struct chunkfile *cf, uint32_t chunk_id, const unsigned char **p, @@ -184,6 +199,20 @@ int pair_chunk(struct chunkfile *cf, return read_chunk(cf, chunk_id, pair_chunk_fn, &pcd); } +int pair_chunk_expect(struct chunkfile *cf, + uint32_t chunk_id, + const unsigned char **p, + size_t record_size, + size_t record_nr) +{ + struct pair_chunk_data pcd = { + .p = p, + .record_size = record_size, + .record_nr = record_nr, + }; + return read_chunk(cf, chunk_id, pair_chunk_expect_fn, &pcd); +} + int read_chunk(struct chunkfile *cf, uint32_t chunk_id, chunk_read_fn fn, diff --git a/chunk-format.h b/chunk-format.h index 14b76180ef..10806d7a9a 100644 --- a/chunk-format.h +++ b/chunk-format.h @@ -17,7 +17,8 @@ struct chunkfile; * * If reading a file, use a NULL 'struct hashfile *' and then call * read_table_of_contents(). Supply the memory-mapped data to the - * pair_chunk() or read_chunk() methods, as appropriate. + * pair_chunk(), pair_chunk_expect(), or read_chunk() methods, as + * appropriate. * * DO NOT MIX THESE MODES. Use different 'struct chunkfile' instances * for reading and writing. @@ -54,6 +55,16 @@ int pair_chunk(struct chunkfile *cf, const unsigned char **p, size_t *size); +/* + * Similar to 'pair_chunk', but used for callers who are reading a chunk + * with a known number of fixed-width records. + */ +int pair_chunk_expect(struct chunkfile *cf, + uint32_t chunk_id, + const unsigned char **p, + size_t record_size, + size_t record_nr); + typedef int (*chunk_read_fn)(const unsigned char *chunk_start, size_t chunk_size, void *data); /* diff --git a/commit-graph.c b/commit-graph.c index 161c47ef64..2aa800d986 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -299,48 +299,6 @@ static int graph_read_oid_fanout(const unsigned char *chunk_start, return 0; } -static int graph_read_oid_lookup(const unsigned char *chunk_start, - size_t chunk_size, void *data) -{ - struct commit_graph *g = data; - g->chunk_oid_lookup = chunk_start; - if (chunk_size / g->hash_len != g->num_commits) - return error(_("commit-graph OID lookup chunk is the wrong size")); - return 0; -} - -static int graph_read_commit_data(const unsigned char *chunk_start, - size_t chunk_size, void *data) -{ - struct commit_graph *g = data; - if (chunk_size / GRAPH_DATA_WIDTH != g->num_commits) - return error(_("commit-graph commit data chunk is wrong size")); - g->chunk_commit_data = chunk_start; - return 0; -} - -static int graph_read_generation_data(const unsigned char *chunk_start, - size_t chunk_size, void *data) -{ - struct commit_graph *g = data; - if (chunk_size / sizeof(uint32_t) != g->num_commits) - return error(_("commit-graph generations chunk is wrong size")); - g->chunk_generation_data = chunk_start; - return 0; -} - -static int graph_read_bloom_index(const unsigned char *chunk_start, - size_t chunk_size, void *data) -{ - struct commit_graph *g = data; - if (chunk_size / 4 != g->num_commits) { - warning(_("commit-graph changed-path index chunk is too small")); - return -1; - } - g->chunk_bloom_indexes = chunk_start; - return 0; -} - static int graph_read_bloom_data(const unsigned char *chunk_start, size_t chunk_size, void *data) { @@ -432,12 +390,15 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s, error(_("commit-graph required OID fanout chunk missing or corrupted")); goto free_and_return; } - if (read_chunk(cf, GRAPH_CHUNKID_OIDLOOKUP, graph_read_oid_lookup, graph)) { - error(_("commit-graph required OID lookup chunk missing or corrupted")); + if (pair_chunk_expect(cf, GRAPH_CHUNKID_OIDLOOKUP, + &graph->chunk_oid_lookup, graph->hash_len, + graph->num_commits)) { + error(_("commit-graph OID lookup chunk is the wrong size")); goto free_and_return; } - if (read_chunk(cf, GRAPH_CHUNKID_DATA, graph_read_commit_data, graph)) { - error(_("commit-graph required commit data chunk missing or corrupted")); + if (pair_chunk_expect(cf, GRAPH_CHUNKID_DATA, &graph->chunk_commit_data, + GRAPH_DATA_WIDTH, graph->num_commits)) { + error(_("commit-graph commit data chunk is wrong size")); goto free_and_return; } @@ -447,8 +408,11 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s, &graph->chunk_base_graphs_size); if (s->commit_graph_generation_version >= 2) { - read_chunk(cf, GRAPH_CHUNKID_GENERATION_DATA, - graph_read_generation_data, graph); + if (pair_chunk_expect(cf, GRAPH_CHUNKID_GENERATION_DATA, + &graph->chunk_generation_data, + sizeof(uint32_t), + graph->num_commits)) + error(_("commit-graph generations chunk is wrong size")); pair_chunk(cf, GRAPH_CHUNKID_GENERATION_DATA_OVERFLOW, &graph->chunk_generation_data_overflow, &graph->chunk_generation_data_overflow_size); @@ -458,8 +422,11 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s, } if (s->commit_graph_changed_paths_version) { - read_chunk(cf, GRAPH_CHUNKID_BLOOMINDEXES, - graph_read_bloom_index, graph); + int res = pair_chunk_expect(cf, GRAPH_CHUNKID_BLOOMINDEXES, + &graph->chunk_bloom_indexes, + sizeof(uint32_t), graph->num_commits); + if (res && res != CHUNK_NOT_FOUND) + warning(_("commit-graph changed-path index chunk is too small")); read_chunk(cf, GRAPH_CHUNKID_BLOOMDATA, graph_read_bloom_data, graph); } diff --git a/midx.c b/midx.c index 1d14661dad..ca41748b74 100644 --- a/midx.c +++ b/midx.c @@ -86,32 +86,6 @@ static int midx_read_oid_fanout(const unsigned char *chunk_start, return 0; } -static int midx_read_oid_lookup(const unsigned char *chunk_start, - size_t chunk_size, void *data) -{ - struct multi_pack_index *m = data; - m->chunk_oid_lookup = chunk_start; - - if (chunk_size != st_mult(m->hash_len, m->num_objects)) { - error(_("multi-pack-index OID lookup chunk is the wrong size")); - return 1; - } - return 0; -} - -static int midx_read_object_offsets(const unsigned char *chunk_start, - size_t chunk_size, void *data) -{ - struct multi_pack_index *m = data; - m->chunk_object_offsets = chunk_start; - - if (chunk_size != st_mult(m->num_objects, MIDX_CHUNK_OFFSET_WIDTH)) { - error(_("multi-pack-index object offset chunk is the wrong size")); - return 1; - } - return 0; -} - struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local) { struct multi_pack_index *m = NULL; @@ -186,9 +160,12 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local die(_("multi-pack-index required pack-name chunk missing or corrupted")); if (read_chunk(cf, MIDX_CHUNKID_OIDFANOUT, midx_read_oid_fanout, m)) die(_("multi-pack-index required OID fanout chunk missing or corrupted")); - if (read_chunk(cf, MIDX_CHUNKID_OIDLOOKUP, midx_read_oid_lookup, m)) + if (pair_chunk_expect(cf, MIDX_CHUNKID_OIDLOOKUP, &m->chunk_oid_lookup, + m->hash_len, m->num_objects)) die(_("multi-pack-index required OID lookup chunk missing or corrupted")); - if (read_chunk(cf, MIDX_CHUNKID_OBJECTOFFSETS, midx_read_object_offsets, m)) + if (pair_chunk_expect(cf, MIDX_CHUNKID_OBJECTOFFSETS, + &m->chunk_object_offsets, MIDX_CHUNK_OFFSET_WIDTH, + m->num_objects)) die(_("multi-pack-index required object offsets chunk missing or corrupted")); pair_chunk(cf, MIDX_CHUNKID_LARGEOFFSETS, &m->chunk_large_offsets, diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh index 7fe7c72a87..91547377ad 100755 --- a/t/t5318-commit-graph.sh +++ b/t/t5318-commit-graph.sh @@ -545,12 +545,12 @@ test_expect_success 'detect missing OID fanout chunk' ' test_expect_success 'detect missing OID lookup chunk' ' corrupt_graph_and_verify $GRAPH_BYTE_OID_LOOKUP_ID "\0" \ - "commit-graph required OID lookup chunk missing or corrupted" + "commit-graph OID lookup chunk is the wrong size" ' test_expect_success 'detect missing commit data chunk' ' corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_DATA_ID "\0" \ - "commit-graph required commit data chunk missing or corrupted" + "commit-graph commit data chunk is wrong size" ' test_expect_success 'detect incorrect fanout' ' @@ -851,7 +851,6 @@ test_expect_success 'reader notices fanout/lookup table mismatch' ' check_corrupt_chunk OIDF 1020 "FFFFFFFF" && cat >expect.err <<-\EOF && error: commit-graph OID lookup chunk is the wrong size - error: commit-graph required OID lookup chunk missing or corrupted EOF test_cmp expect.err err ' @@ -876,7 +875,6 @@ test_expect_success 'reader notices too-small commit data chunk' ' check_corrupt_chunk CDAT clear 00000000 && cat >expect.err <<-\EOF && error: commit-graph commit data chunk is wrong size - error: commit-graph required commit data chunk missing or corrupted EOF test_cmp expect.err err ' diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh index c20aafe99a..ea3788ef8a 100755 --- a/t/t5319-multi-pack-index.sh +++ b/t/t5319-multi-pack-index.sh @@ -1077,7 +1077,6 @@ test_expect_success 'reader notices too-small oid lookup chunk' ' corrupt_chunk OIDL clear 00000000 && test_must_fail git log 2>err && cat >expect <<-\EOF && - error: multi-pack-index OID lookup chunk is the wrong size fatal: multi-pack-index required OID lookup chunk missing or corrupted EOF test_cmp expect err @@ -1112,7 +1111,6 @@ test_expect_success 'reader notices too-small object offset chunk' ' corrupt_chunk OOFF clear 00000000 && test_must_fail git log 2>err && cat >expect <<-\EOF && - error: multi-pack-index object offset chunk is the wrong size fatal: multi-pack-index required object offsets chunk missing or corrupted EOF test_cmp expect err