Skip to content

Commit 72a9a08

Browse files
peffgitster
authored andcommitted
midx: check size of pack names chunk
We parse the pack-name chunk as a series of NUL-terminated strings. But since we don't look at the chunk size, there's nothing to guarantee that we don't parse off the end of the chunk (or even off the end of the mapped file). We can record the length, and then as we parse make sure that we never walk past it. The new test exercises the case, though note that it does not actually segfault before this patch. It hits a NUL byte somewhere in one of the other chunks, and comes up with a garbage pack name. You could construct one that reads out-of-bounds (e.g., a PNAM chunk at the end of file), but this case is simple and sufficient to check that we detect the problem. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4169d89 commit 72a9a08

File tree

3 files changed

+21
-2
lines changed

3 files changed

+21
-2
lines changed

midx.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
157157
MIDX_HEADER_SIZE, m->num_chunks))
158158
goto cleanup_fail;
159159

160-
if (pair_chunk_unsafe(cf, MIDX_CHUNKID_PACKNAMES, &m->chunk_pack_names))
160+
if (pair_chunk(cf, MIDX_CHUNKID_PACKNAMES, &m->chunk_pack_names, &m->chunk_pack_names_len))
161161
die(_("multi-pack-index required pack-name chunk missing or corrupted"));
162162
if (read_chunk(cf, MIDX_CHUNKID_OIDFANOUT, midx_read_oid_fanout, m))
163163
die(_("multi-pack-index required OID fanout chunk missing or corrupted"));
@@ -176,9 +176,16 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
176176

177177
cur_pack_name = (const char *)m->chunk_pack_names;
178178
for (i = 0; i < m->num_packs; i++) {
179+
const char *end;
180+
size_t avail = m->chunk_pack_names_len -
181+
(cur_pack_name - (const char *)m->chunk_pack_names);
182+
179183
m->pack_names[i] = cur_pack_name;
180184

181-
cur_pack_name += strlen(cur_pack_name) + 1;
185+
end = memchr(cur_pack_name, '\0', avail);
186+
if (!end)
187+
die(_("multi-pack-index pack-name chunk is too short"));
188+
cur_pack_name = end + 1;
182189

183190
if (i && strcmp(m->pack_names[i], m->pack_names[i - 1]) <= 0)
184191
die(_("multi-pack-index pack names out of order: '%s' before '%s'"),

midx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct multi_pack_index {
3232
int local;
3333

3434
const unsigned char *chunk_pack_names;
35+
size_t chunk_pack_names_len;
3536
const uint32_t *chunk_oid_fanout;
3637
const unsigned char *chunk_oid_lookup;
3738
const unsigned char *chunk_object_offsets;

t/t5319-multi-pack-index.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,4 +1083,15 @@ test_expect_success 'reader notices too-small oid lookup chunk' '
10831083
test_cmp expect err
10841084
'
10851085

1086+
test_expect_success 'reader notices too-small pack names chunk' '
1087+
# There is no NUL to terminate the name here, so the
1088+
# chunk is too short.
1089+
corrupt_chunk PNAM clear 70656666 &&
1090+
test_must_fail git log 2>err &&
1091+
cat >expect <<-\EOF &&
1092+
fatal: multi-pack-index pack-name chunk is too short
1093+
EOF
1094+
test_cmp expect err
1095+
'
1096+
10861097
test_done

0 commit comments

Comments
 (0)