diff --git a/chunk-format.c b/chunk-format.c index 140dfa0dcc..8d910e23f6 100644 --- a/chunk-format.c +++ b/chunk-format.c @@ -154,20 +154,36 @@ int read_table_of_contents(struct chunkfile *cf, return 0; } +struct pair_chunk_data { + const unsigned char **p; + size_t *size; +}; + static int pair_chunk_fn(const unsigned char *chunk_start, size_t chunk_size, void *data) { - const unsigned char **p = data; - *p = chunk_start; + struct pair_chunk_data *pcd = data; + *pcd->p = chunk_start; + *pcd->size = chunk_size; return 0; } int pair_chunk(struct chunkfile *cf, uint32_t chunk_id, - const unsigned char **p) + const unsigned char **p, + size_t *size) { - return read_chunk(cf, chunk_id, pair_chunk_fn, p); + struct pair_chunk_data pcd = { .p = p, .size = size }; + return read_chunk(cf, chunk_id, pair_chunk_fn, &pcd); +} + +int pair_chunk_unsafe(struct chunkfile *cf, + uint32_t chunk_id, + const unsigned char **p) +{ + size_t dummy; + return pair_chunk(cf, chunk_id, p, &dummy); } int read_chunk(struct chunkfile *cf, diff --git a/chunk-format.h b/chunk-format.h index c7794e84ad..8dce7967f4 100644 --- a/chunk-format.h +++ b/chunk-format.h @@ -43,13 +43,28 @@ int read_table_of_contents(struct chunkfile *cf, /* * Find 'chunk_id' in the given chunkfile and assign the * given pointer to the position in the mmap'd file where - * that chunk begins. + * that chunk begins. Likewise the "size" parameter is filled + * with the size of the chunk. * * Returns CHUNK_NOT_FOUND if the chunk does not exist. */ int pair_chunk(struct chunkfile *cf, uint32_t chunk_id, - const unsigned char **p); + const unsigned char **p, + size_t *size); + +/* + * Unsafe version of pair_chunk; it does not return the size, + * meaning that the caller cannot possibly be careful about + * reading out of bounds from the mapped memory. + * + * No new callers should use this function, and old callers should + * be audited and migrated over to using the regular pair_chunk() + * function. + */ +int pair_chunk_unsafe(struct chunkfile *cf, + uint32_t chunk_id, + const unsigned char **p); 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 1a56efcf69..a689a55b79 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -394,17 +394,17 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s, GRAPH_HEADER_SIZE, graph->num_chunks)) goto free_and_return; - pair_chunk(cf, GRAPH_CHUNKID_OIDFANOUT, + pair_chunk_unsafe(cf, GRAPH_CHUNKID_OIDFANOUT, (const unsigned char **)&graph->chunk_oid_fanout); read_chunk(cf, GRAPH_CHUNKID_OIDLOOKUP, graph_read_oid_lookup, graph); - pair_chunk(cf, GRAPH_CHUNKID_DATA, &graph->chunk_commit_data); - pair_chunk(cf, GRAPH_CHUNKID_EXTRAEDGES, &graph->chunk_extra_edges); - pair_chunk(cf, GRAPH_CHUNKID_BASE, &graph->chunk_base_graphs); + pair_chunk_unsafe(cf, GRAPH_CHUNKID_DATA, &graph->chunk_commit_data); + pair_chunk_unsafe(cf, GRAPH_CHUNKID_EXTRAEDGES, &graph->chunk_extra_edges); + pair_chunk_unsafe(cf, GRAPH_CHUNKID_BASE, &graph->chunk_base_graphs); if (s->commit_graph_generation_version >= 2) { - pair_chunk(cf, GRAPH_CHUNKID_GENERATION_DATA, + pair_chunk_unsafe(cf, GRAPH_CHUNKID_GENERATION_DATA, &graph->chunk_generation_data); - pair_chunk(cf, GRAPH_CHUNKID_GENERATION_DATA_OVERFLOW, + pair_chunk_unsafe(cf, GRAPH_CHUNKID_GENERATION_DATA_OVERFLOW, &graph->chunk_generation_data_overflow); if (graph->chunk_generation_data) @@ -412,7 +412,7 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s, } if (s->commit_graph_read_changed_paths) { - pair_chunk(cf, GRAPH_CHUNKID_BLOOMINDEXES, + pair_chunk_unsafe(cf, GRAPH_CHUNKID_BLOOMINDEXES, &graph->chunk_bloom_indexes); read_chunk(cf, GRAPH_CHUNKID_BLOOMDATA, graph_read_bloom_data, graph); diff --git a/midx.c b/midx.c index 931f557350..3165218ab5 100644 --- a/midx.c +++ b/midx.c @@ -143,19 +143,19 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local MIDX_HEADER_SIZE, m->num_chunks)) goto cleanup_fail; - if (pair_chunk(cf, MIDX_CHUNKID_PACKNAMES, &m->chunk_pack_names) == CHUNK_NOT_FOUND) + if (pair_chunk_unsafe(cf, MIDX_CHUNKID_PACKNAMES, &m->chunk_pack_names) == CHUNK_NOT_FOUND) die(_("multi-pack-index missing required pack-name chunk")); if (read_chunk(cf, MIDX_CHUNKID_OIDFANOUT, midx_read_oid_fanout, m) == CHUNK_NOT_FOUND) die(_("multi-pack-index missing required OID fanout chunk")); - if (pair_chunk(cf, MIDX_CHUNKID_OIDLOOKUP, &m->chunk_oid_lookup) == CHUNK_NOT_FOUND) + if (pair_chunk_unsafe(cf, MIDX_CHUNKID_OIDLOOKUP, &m->chunk_oid_lookup) == CHUNK_NOT_FOUND) die(_("multi-pack-index missing required OID lookup chunk")); - if (pair_chunk(cf, MIDX_CHUNKID_OBJECTOFFSETS, &m->chunk_object_offsets) == CHUNK_NOT_FOUND) + if (pair_chunk_unsafe(cf, MIDX_CHUNKID_OBJECTOFFSETS, &m->chunk_object_offsets) == CHUNK_NOT_FOUND) die(_("multi-pack-index missing required object offsets chunk")); - pair_chunk(cf, MIDX_CHUNKID_LARGEOFFSETS, &m->chunk_large_offsets); + pair_chunk_unsafe(cf, MIDX_CHUNKID_LARGEOFFSETS, &m->chunk_large_offsets); if (git_env_bool("GIT_TEST_MIDX_READ_RIDX", 1)) - pair_chunk(cf, MIDX_CHUNKID_REVINDEX, &m->chunk_revindex); + pair_chunk_unsafe(cf, MIDX_CHUNKID_REVINDEX, &m->chunk_revindex); m->num_objects = ntohl(m->chunk_oid_fanout[255]);