diff options
| author | Junio C Hamano <gitster@pobox.com> | 2025-05-30 11:59:16 -0700 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2025-05-30 11:59:16 -0700 |
| commit | 48a25bbbbb26f7d140986a9f2a1d5d6c68eec6a4 (patch) | |
| tree | 86221cffe6f124e0bcea6237180958f4a32f3a2b | |
| parent | Merge branch 'cb/reftable-unused-portability-fix' (diff) | |
| parent | midx docs: clarify tie breaking (diff) | |
| download | git-48a25bbbbb26f7d140986a9f2a1d5d6c68eec6a4.tar.gz git-48a25bbbbb26f7d140986a9f2a1d5d6c68eec6a4.zip | |
Merge branch 'pw/midx-repack-overflow-fix'
Integer overflow fix around code paths for "git multi-pack-index repack"..
* pw/midx-repack-overflow-fix:
midx docs: clarify tie breaking
midx: avoid negative array index
midx repack: avoid potential integer overflow on 64 bit systems
midx repack: avoid integer overflow on 32 bit systems
Diffstat (limited to '')
| -rw-r--r-- | Documentation/git-multi-pack-index.adoc | 11 | ||||
| -rw-r--r-- | git-compat-util.h | 16 | ||||
| -rw-r--r-- | midx-write.c | 22 |
3 files changed, 39 insertions, 10 deletions
diff --git a/Documentation/git-multi-pack-index.adoc b/Documentation/git-multi-pack-index.adoc index 631d5c7d15..b6cd0d7f85 100644 --- a/Documentation/git-multi-pack-index.adoc +++ b/Documentation/git-multi-pack-index.adoc @@ -38,10 +38,13 @@ write:: + -- --preferred-pack=<pack>:: - Optionally specify the tie-breaking pack used when - multiple packs contain the same object. `<pack>` must - contain at least one object. If not given, ties are - broken in favor of the pack with the lowest mtime. + When specified, break ties in favor of this pack when + there are additional copies of its objects in other + packs. Ties for objects not found in the preferred + pack are always resolved in favor of the copy in the + pack with the highest mtime. If unspecified, the pack + with the lowest mtime is used by default. The + preferred pack must have at least one object. --[no-]bitmap:: Control whether or not a multi-pack bitmap is written. diff --git a/git-compat-util.h b/git-compat-util.h index 36b9577c8d..4678e21c4c 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -668,6 +668,22 @@ static inline int cast_size_t_to_int(size_t a) return (int)a; } +static inline uint64_t u64_mult(uint64_t a, uint64_t b) +{ + if (unsigned_mult_overflows(a, b)) + die("uint64_t overflow: %"PRIuMAX" * %"PRIuMAX, + (uintmax_t)a, (uintmax_t)b); + return a * b; +} + +static inline uint64_t u64_add(uint64_t a, uint64_t b) +{ + if (unsigned_add_overflows(a, b)) + die("uint64_t overflow: %"PRIuMAX" + %"PRIuMAX, + (uintmax_t)a, (uintmax_t)b); + return a + b; +} + /* * Limit size of IO chunks, because huge chunks only cause pain. OS X * 64-bit is buggy, returning EINVAL if len >= INT_MAX; and even in diff --git a/midx-write.c b/midx-write.c index dd3b3070e5..ba4a94950a 100644 --- a/midx-write.c +++ b/midx-write.c @@ -1566,7 +1566,7 @@ int expire_midx_packs(struct repository *r, const char *object_dir, unsigned fla _("Counting referenced objects"), m->num_objects); for (i = 0; i < m->num_objects; i++) { - int pack_int_id = nth_midxed_pack_int_id(m, i); + uint32_t pack_int_id = nth_midxed_pack_int_id(m, i); count[pack_int_id]++; display_progress(progress, i + 1); } @@ -1697,21 +1697,31 @@ static void fill_included_packs_batch(struct repository *r, total_size = 0; for (i = 0; total_size < batch_size && i < m->num_packs; i++) { - int pack_int_id = pack_info[i].pack_int_id; + uint32_t pack_int_id = pack_info[i].pack_int_id; struct packed_git *p = m->packs[pack_int_id]; - size_t expected_size; + uint64_t expected_size; if (!want_included_pack(r, m, pack_kept_objects, pack_int_id)) continue; - expected_size = st_mult(p->pack_size, - pack_info[i].referenced_objects); + /* + * Use shifted integer arithmetic to calculate the + * expected pack size to ~4 significant digits without + * overflow for packsizes less that 1PB. + */ + expected_size = (uint64_t)pack_info[i].referenced_objects << 14; expected_size /= p->num_objects; + expected_size = u64_mult(expected_size, p->pack_size); + expected_size = u64_add(expected_size, 1u << 13) >> 14; if (expected_size >= batch_size) continue; - total_size += expected_size; + if (unsigned_add_overflows(total_size, (size_t)expected_size)) + total_size = SIZE_MAX; + else + total_size += expected_size; + include_pack[pack_int_id] = 1; } |
