diff options
author | Jeff King <peff@peff.net> | 2023-10-09 23:58:23 +0300 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2023-10-10 01:55:00 +0300 |
commit | 570b8b883617df2acfedab88b9f5af0b50c821cd (patch) | |
tree | 8442f93f89a238bdb66a7851175570cce98000d5 /chunk-format.c | |
parent | 3a06386e314565108ad56a9bdb8f7b80ac52fb69 (diff) |
chunk-format: note that pair_chunk() is unsafe
The pair_chunk() function is provided as an easy helper for parsing
chunks that just want a pointer to a set of bytes. But every caller has
a hidden bug: because we return only the pointer without the matching
chunk size, the callers have no clue how many bytes they are allowed to
look at. And as a result, they may read off the end of the mmap'd data
when the on-disk file does not match their expectations.
Since chunk files are typically used for local-repository data like
commit-graph files and midx's, the security implications here are pretty
mild. The worst that can happen is that you hand somebody a corrupted
repository tarball, and running Git on it does an out-of-bounds read and
crashes. So it's worth being more defensive, but we don't need to drop
everything and fix every caller immediately.
I noticed the problem because the pair_chunk_fn() callback does not look
at its chunk_size argument, and wanted to annotate it to silence
-Wunused-parameter. We could do that now, but we'd lose the hint that
this code should be audited and fixed.
So instead, let's set ourselves up for going down that path:
1. Provide a pair_chunk() function that does return the size, which
prepares us for fixing these cases.
2. Rename the existing function to pair_chunk_unsafe(). That gives us
an easy way to grep for cases which still need to be fixed, and the
name should cause anybody adding new calls to think twice before
using it.
There are no callers of the "safe" version yet, but we'll add some in
subsequent patches.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'chunk-format.c')
-rw-r--r-- | chunk-format.c | 24 |
1 files changed, 20 insertions, 4 deletions
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) +{ + 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) { - return read_chunk(cf, chunk_id, pair_chunk_fn, p); + size_t dummy; + return pair_chunk(cf, chunk_id, p, &dummy); } int read_chunk(struct chunkfile *cf, |