midx: validate incremental MIDX pack IDs
Incremental MIDX support made object-offset pack IDs local to each layer and then converted them to chain-global IDs by adding `num_packs_in_base`. The conversion was introduced byjch19419821ba(midx: teach `nth_midxed_pack_int_id()` about incremental MIDXs, 2024-08-06). Chain-aware pack preparation followed in1820bd878c(midx: teach `prepare_midx_pack()` about incremental MIDXs, 2024-08-06), but the final `midx_fill_entry()` lookup remained tied to the original layer. Only with8f909ff4e9(packfile: recover when a multi-pack-index names a removed pack, 2026-08-29) did Coverity point out this issue: a local ID such as `UINT32_MAX` could wrap when the base-pack count was added, producing a plausible but incorrect global ID. After `prepare_midx_pack()` resolved the chain, `midx_fill_entry()` could then underflow or address the wrong layer while indexing the current layer's pack array, causing an invalid memory access and crashing Git. Validate each local pack ID against its layer's pack count before adding the base count, and obtain the final pack through `nth_midxed_pack()`, which resolves the correct MIDX layer. This prevents an invalid local ID from wrapping during conversion and ensures that the lookup uses the layer identified by the resolved chain-global ID. Assisted-by: GPT-5.6 Luna Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
parent
723dd6ca3e
commit
c3a6be2333
14
midx.c
14
midx.c
|
|
@ -583,10 +583,16 @@ off_t nth_midxed_offset(struct multi_pack_index *m, uint32_t pos)
|
|||
|
||||
uint32_t nth_midxed_pack_int_id(struct multi_pack_index *m, uint32_t pos)
|
||||
{
|
||||
pos = midx_for_object(&m, pos);
|
||||
uint32_t pack_int_id;
|
||||
|
||||
return m->num_packs_in_base + get_be32(m->chunk_object_offsets +
|
||||
(off_t)pos * MIDX_CHUNK_OFFSET_WIDTH);
|
||||
pos = midx_for_object(&m, pos);
|
||||
pack_int_id = get_be32(m->chunk_object_offsets +
|
||||
(off_t)pos * MIDX_CHUNK_OFFSET_WIDTH);
|
||||
if (pack_int_id >= m->num_packs)
|
||||
die(_("bad pack-int-id: %"PRIu32" (%"PRIu32" total packs)"),
|
||||
pack_int_id, m->num_packs);
|
||||
|
||||
return m->num_packs_in_base + pack_int_id;
|
||||
}
|
||||
|
||||
enum midx_fill_result midx_fill_entry(struct multi_pack_index *m,
|
||||
|
|
@ -606,7 +612,7 @@ enum midx_fill_result midx_fill_entry(struct multi_pack_index *m,
|
|||
|
||||
if (prepare_midx_pack(m, pack_int_id))
|
||||
return MIDX_FILL_OWNER_UNAVAILABLE;
|
||||
p = m->packs[pack_int_id - m->num_packs_in_base];
|
||||
p = nth_midxed_pack(m, pack_int_id);
|
||||
|
||||
/*
|
||||
* We are about to tell the caller where they can locate the
|
||||
|
|
|
|||
Loading…
Reference in New Issue