bisect: fix various cases where we leak commit list items

There are various cases where we leak commit list items because we evict items from the list, but don't free them. Plug those. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Nov 20, 2024 at 14:39 UTC c1e98f90103e8d98ef441ce8f609cf3bc8fa538b
2 files changed +23 -8
bisect.c
+22 -8
@@ -442,9 +442,12 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
442 best->next = NULL;
443 }
444 *reaches = weight(best);
445 + } else {
446 + free_commit_list(*commit_list);
447 }
446 - free(weights);
448 *commit_list = best;
449 +
450 + free(weights);
451 clear_commit_weight(&commit_weight);
452 }
453
@@ -557,8 +560,11 @@ struct commit_list *filter_skipped(struct commit_list *list,
560 tried = &list->next;
561 } else {
562 if (!show_all) {
560 - if (!skipped_first || !*skipped_first)
563 + if (!skipped_first || !*skipped_first) {
564 + free_commit_list(next);
565 + free_commit_list(filtered);
566 return list;
567 + }
568 } else if (skipped_first && !*skipped_first) {
569 /* This means we know it's not skipped */
570 *skipped_first = -1;
@@ -614,7 +620,7 @@ static int sqrti(int val)
620
621 static struct commit_list *skip_away(struct commit_list *list, int count)
622 {
617 - struct commit_list *cur, *previous;
623 + struct commit_list *cur, *previous, *result = list;
624 int prn, index, i;
625
626 prn = get_prn(count);
@@ -626,15 +632,23 @@ static struct commit_list *skip_away(struct commit_list *list, int count)
632 for (i = 0; cur; cur = cur->next, i++) {
633 if (i == index) {
634 if (!oideq(&cur->item->object.oid, current_bad_oid))
629 - return cur;
630 - if (previous)
631 - return previous;
632 - return list;
635 + result = cur;
636 + else if (previous)
637 + result = previous;
638 + else
639 + result = list;
640 + break;
641 }
642 previous = cur;
643 }
644
637 - return list;
645 + for (cur = list; cur != result; ) {
646 + struct commit_list *next = cur->next;
647 + free(cur);
648 + cur = next;
649 + }
650 +
651 + return result;
652 }
653
654 static struct commit_list *managed_skipped(struct commit_list *list,
t/t6030-bisect-porcelain.sh
+1
@@ -9,6 +9,7 @@ exec </dev/null
9 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
10 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
11
12 +TEST_PASSES_SANITIZE_LEAK=true
13 . ./test-lib.sh
14
15 add_line_into_file()