pack-bitmap.c: ensure that eindex lookups don't overflow

When a bitmap is used to answer some reachability query, it creates a pseudo-bitmap called the "extended index" on top of any existing bitmaps to store objects that are relevant to the query, but not mentioned in the bitmap. When looking up the ith object in the extended index in a bitmap, it is common to write something like: bitmap_get(result, i + bitmap_num_objects(bitmap_git)) , indicating that we want the ith object following all other objects mentioned in the bitmap_git. Since the type of `i` and the return type of `bitmap_num_objects()` are both `uint32_t`s, But if there are either a large number of objects in the bitmap, or a large number of objects in the extended index (or both), this addition can overflow when the sum is greater than 2^32-1. Having that large of a bitmap position is entirely acceptable, but we need to ensure that the computed bitmap position for that object is performed using 64-bits and doesn't overflow. 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 0948c501761585bdf3e4e1133700c2eb867d88e6
1 file changed +7 -5
pack-bitmap.c
+7 -5
@@ -1152,7 +1152,7 @@ static void show_extended_objects(struct bitmap_index *bitmap_git,
1152 for (i = 0; i < eindex->count; ++i) {
1153 struct object *obj;
1154
1155 - if (!bitmap_get(objects, bitmap_num_objects(bitmap_git) + i))
1155 + if (!bitmap_get(objects, st_add(bitmap_num_objects(bitmap_git), i)))
1156 continue;
1157
1158 obj = eindex->objects[i];
@@ -1331,7 +1331,7 @@ static void filter_bitmap_exclude_type(struct bitmap_index *bitmap_git,
1331 * them individually.
1332 */
1333 for (i = 0; i < eindex->count; i++) {
1334 - uint32_t pos = i + bitmap_num_objects(bitmap_git);
1334 + size_t pos = st_add(i, bitmap_num_objects(bitmap_git));
1335 if (eindex->objects[i]->type == type &&
1336 bitmap_get(to_filter, pos) &&
1337 !bitmap_get(tips, pos))
@@ -1422,7 +1422,7 @@ static void filter_bitmap_blob_limit(struct bitmap_index *bitmap_git,
1422 }
1423
1424 for (i = 0; i < eindex->count; i++) {
1425 - uint32_t pos = i + bitmap_num_objects(bitmap_git);
1425 + size_t pos = st_add(i, bitmap_num_objects(bitmap_git));
1426 if (eindex->objects[i]->type == OBJ_BLOB &&
1427 bitmap_get(to_filter, pos) &&
1428 !bitmap_get(tips, pos) &&
@@ -1873,7 +1873,8 @@ static uint32_t count_object_type(struct bitmap_index *bitmap_git,
1873
1874 for (i = 0; i < eindex->count; ++i) {
1875 if (eindex->objects[i]->type == type &&
1876 - bitmap_get(objects, bitmap_num_objects(bitmap_git) + i))
1876 + bitmap_get(objects,
1877 + st_add(bitmap_num_objects(bitmap_git), i)))
1878 count++;
1879 }
1880
@@ -2287,7 +2288,8 @@ static off_t get_disk_usage_for_extended(struct bitmap_index *bitmap_git)
2288 for (i = 0; i < eindex->count; i++) {
2289 struct object *obj = eindex->objects[i];
2290
2290 - if (!bitmap_get(result, bitmap_num_objects(bitmap_git) + i))
2291 + if (!bitmap_get(result,
2292 + st_add(bitmap_num_objects(bitmap_git), i)))
2293 continue;
2294
2295 if (oid_object_info_extended(the_repository, &obj->oid, &oi, 0) < 0)