midx.c: prevent overflow in `write_midx_internal()`

When writing a MIDX, we use the chunk-format API to write out each individual chunk of the MIDX. Each chunk of the MIDX is tracked via a call to `add_chunk()`, along with the expected size of that chunk. Guard against overflow when dealing with a MIDX with a large number of entries (and consequently, large chunks within the MIDX file itself) to avoid corrupting the contents of the MIDX itself. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed Jul 12, 2023 at 19:37 UTC 2bc764c1d4d1bc12ba7d95ceebb0da54ba381be5
1 file changed +5 -4
midx.c
+5 -4
@@ -1501,21 +1501,22 @@ static int write_midx_internal(const char *object_dir,
1501 add_chunk(cf, MIDX_CHUNKID_OIDFANOUT, MIDX_CHUNK_FANOUT_SIZE,
1502 write_midx_oid_fanout);
1503 add_chunk(cf, MIDX_CHUNKID_OIDLOOKUP,
1504 - (size_t)ctx.entries_nr * the_hash_algo->rawsz,
1504 + st_mult(ctx.entries_nr, the_hash_algo->rawsz),
1505 write_midx_oid_lookup);
1506 add_chunk(cf, MIDX_CHUNKID_OBJECTOFFSETS,
1507 - (size_t)ctx.entries_nr * MIDX_CHUNK_OFFSET_WIDTH,
1507 + st_mult(ctx.entries_nr, MIDX_CHUNK_OFFSET_WIDTH),
1508 write_midx_object_offsets);
1509
1510 if (ctx.large_offsets_needed)
1511 add_chunk(cf, MIDX_CHUNKID_LARGEOFFSETS,
1512 - (size_t)ctx.num_large_offsets * MIDX_CHUNK_LARGE_OFFSET_WIDTH,
1512 + st_mult(ctx.num_large_offsets,
1513 + MIDX_CHUNK_LARGE_OFFSET_WIDTH),
1514 write_midx_large_offsets);
1515
1516 if (flags & (MIDX_WRITE_REV_INDEX | MIDX_WRITE_BITMAP)) {
1517 ctx.pack_order = midx_pack_order(&ctx);
1518 add_chunk(cf, MIDX_CHUNKID_REVINDEX,
1518 - ctx.entries_nr * sizeof(uint32_t),
1519 + st_mult(ctx.entries_nr, sizeof(uint32_t)),
1520 write_midx_revindex);
1521 }
1522