builtin/gc: fix signedness issues in ODB-related functionality

There are a couple of signedness issues in ODB-related functionality. These are not a problem because we disable -Wsign-compare in this file, but once we move these functions into "odb/source-files.c" they will result in warnings. Fix those issues: - In `too_many_loose_objects()` we receive a signed limit, but compare it with the unsigned actual number of loose objects. This is fixed by bailing out immediately when the limit is smaller than or equal to zero, which we also do similarly in other places. The warning is then squelched via a cast. - In `find_base_packs()` we compare the signed size of the pack against the unsigned limit. As the pack size is always going to be a positive file size it's safe to cast it to an unsigned value. - In `odb_optimize()` we compare the unsigned `keep_pack.nr` value against the signed `gc_auto_pack_limit`. We only reach this code when `too_many_packs()` returns true-ish, and that can only happen when `gc_auto_pack_limit > 0`. Consequently, we can fix the warning by casting the limit to an unsigned value. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jul 13, 2026 at 07:52 UTC 7534d456816d49f20716e49900d43cedb02e8c42
1 file changed +11 -9
builtin/gc.c
+11 -9
@@ -430,19 +430,21 @@ out:
430
431 static int too_many_loose_objects(struct odb_source_files *files, int limit)
432 {
433 - /*
434 - * This is weird, but stems from legacy behaviour: the GC auto
435 - * threshold was always essentially interpreted as if it was rounded up
436 - * to the next multiple 256 of, so we retain this behaviour for now.
437 - */
438 - int auto_threshold = DIV_ROUND_UP(limit, 256) * 256;
433 unsigned long loose_count;
434
435 + if (limit <= 0)
436 + return 0;
437 +
438 if (odb_source_count_objects(&files->loose->base, ODB_COUNT_OBJECTS_APPROXIMATE,
439 &loose_count) < 0)
440 return 0;
441
445 - return loose_count > auto_threshold;
442 + /*
443 + * This is weird, but stems from legacy behaviour: the GC auto
444 + * threshold was always essentially interpreted as if it was rounded up
445 + * to the next multiple 256 of, so we retain this behaviour for now.
446 + */
447 + return loose_count > (DIV_ROUND_UP(((unsigned long) limit), 256) * 256);
448 }
449
450 static struct packed_git *find_base_packs(struct odb_source_files *files,
@@ -456,7 +458,7 @@ static struct packed_git *find_base_packs(struct odb_source_files *files,
458 if (e->pack->is_cruft)
459 continue;
460 if (limit) {
459 - if (e->pack->pack_size >= limit)
461 + if ((uintmax_t) e->pack->pack_size >= limit)
462 string_list_append(packs, e->pack->pack_name);
463 } else if (!base || base->pack_size < e->pack->pack_size) {
464 base = e->pack;
@@ -946,7 +948,7 @@ static int odb_optimize(struct object_database *odb,
948
949 if (big_pack_threshold) {
950 find_base_packs(files, &keep_pack, big_pack_threshold);
949 - if (keep_pack.nr >= gc_auto_pack_limit) {
951 + if (keep_pack.nr >= (unsigned long) gc_auto_pack_limit) {
952 string_list_clear(&keep_pack, 0);
953 find_base_packs(files, &keep_pack, 0);
954 }