send-pack: fix leaking common object IDs

We're leaking the array of common object IDs in `send_pack()`. Fix this by creating a common exit path where we free the leaking data. While at it, unify some other cleanups now that we have a central place to put them. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Sep 5, 2024 at 12:08 UTC e03004f7f86a817af2b8d0752dfecac58e7d85e0
2 files changed +23 -12
send-pack.c
+22 -12
@@ -508,7 +508,8 @@ int send_pack(struct send_pack_args *args,
508 if (!remote_refs) {
509 fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
510 "Perhaps you should specify a branch.\n");
511 - return 0;
511 + ret = 0;
512 + goto out;
513 }
514
515 git_config_get_bool("push.negotiate", &push_negotiate);
@@ -615,12 +616,11 @@ int send_pack(struct send_pack_args *args,
616 * atomically, abort the whole operation.
617 */
618 if (use_atomic) {
618 - strbuf_release(&req_buf);
619 - strbuf_release(&cap_buf);
619 reject_atomic_push(remote_refs, args->send_mirror);
620 error("atomic push failed for ref %s. status: %d\n",
621 ref->name, ref->status);
623 - return args->porcelain ? 0 : -1;
622 + ret = args->porcelain ? 0 : -1;
623 + goto out;
624 }
625 /* else fallthrough */
626 default:
@@ -682,8 +682,6 @@ int send_pack(struct send_pack_args *args,
682 write_or_die(out, req_buf.buf, req_buf.len);
683 packet_flush(out);
684 }
685 - strbuf_release(&req_buf);
686 - strbuf_release(&cap_buf);
685
686 if (use_sideband && cmds_sent) {
687 memset(&demux, 0, sizeof(demux));
@@ -721,7 +719,9 @@ int send_pack(struct send_pack_args *args,
719 finish_async(&demux);
720 }
721 fd[1] = -1;
724 - return -1;
722 +
723 + ret = -1;
724 + goto out;
725 }
726 if (!args->stateless_rpc)
727 /* Closed by pack_objects() via start_command() */
@@ -746,10 +746,12 @@ int send_pack(struct send_pack_args *args,
746 }
747
748 if (ret < 0)
749 - return ret;
749 + goto out;
750
751 - if (args->porcelain)
752 - return 0;
751 + if (args->porcelain) {
752 + ret = 0;
753 + goto out;
754 + }
755
756 for (ref = remote_refs; ref; ref = ref->next) {
757 switch (ref->status) {
@@ -758,8 +760,16 @@ int send_pack(struct send_pack_args *args,
760 case REF_STATUS_OK:
761 break;
762 default:
761 - return -1;
763 + ret = -1;
764 + goto out;
765 }
766 }
764 - return 0;
767 +
768 + ret = 0;
769 +
770 +out:
771 + oid_array_clear(&commons);
772 + strbuf_release(&req_buf);
773 + strbuf_release(&cap_buf);
774 + return ret;
775 }
t/t5549-fetch-push-http.sh
+1
@@ -5,6 +5,7 @@ test_description='fetch/push functionality using the HTTP protocol'
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7
8 +TEST_PASSES_SANITIZE_LEAK=true
9 . ./test-lib.sh
10 . "$TEST_DIRECTORY"/lib-httpd.sh
11 start_httpd