bundle: plug leaks in `create_bundle()`
When creating a bundle, we set up a revision walk, but never release data associated with it. Furthermore, we create a mostly-shallow copy of that revision walk where we only adapt its pending objects such that we can reuse the walk. While that copy must not be released, the pending objects array need to be. Plug those memory leaks by releasing the revision walk and the pending objects of the copied revision walk. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Jun 11, 2024 at 11:19 UTC
11ee9a75e7d6f149431f69400c81006f8ccecad5
4 files changed
+22
-10
bundle.c
+19
-10
@@ -500,6 +500,7 @@ int create_bundle(struct repository *r, const char *path,
500
struct rev_info revs, revs_copy;
501
int min_version = 2;
502
struct bundle_prerequisites_info bpi;
503
+ int ret;
504
int i;
505
506
/* init revs to list objects for pack-objects later */
@@ -525,8 +526,8 @@ int create_bundle(struct repository *r, const char *path,
526
min_version = 3;
527
528
if (argc > 1) {
528
- error(_("unrecognized argument: %s"), argv[1]);
529
- goto err;
529
+ ret = error(_("unrecognized argument: %s"), argv[1]);
530
+ goto out;
531
}
532
533
bundle_to_stdout = !strcmp(path, "-");
@@ -591,23 +592,31 @@ int create_bundle(struct repository *r, const char *path,
592
593
/* write bundle refs */
594
ref_count = write_bundle_refs(bundle_fd, &revs_copy);
594
- if (!ref_count)
595
+ if (!ref_count) {
596
die(_("Refusing to create empty bundle."));
596
- else if (ref_count < 0)
597
- goto err;
597
+ } else if (ref_count < 0) {
598
+ ret = -1;
599
+ goto out;
600
+ }
601
602
/* write pack */
600
- if (write_pack_data(bundle_fd, &revs_copy, pack_options))
601
- goto err;
603
+ if (write_pack_data(bundle_fd, &revs_copy, pack_options)) {
604
+ ret = -1;
605
+ goto out;
606
+ }
607
608
if (!bundle_to_stdout) {
609
if (commit_lock_file(&lock))
610
die_errno(_("cannot create '%s'"), path);
611
}
607
- return 0;
608
-err:
612
+
613
+ ret = 0;
614
+
615
+out:
616
+ object_array_clear(&revs_copy.pending);
617
+ release_revisions(&revs);
618
rollback_lock_file(&lock);
610
- return -1;
619
+ return ret;
620
}
621
622
int unbundle(struct repository *r, struct bundle_header *header,
t/t5605-clone-local.sh
+1
@@ -4,6 +4,7 @@ test_description='test local clone'
4
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
5
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
6
7
+TEST_PASSES_SANITIZE_LEAK=true
8
. ./test-lib.sh
9
10
repo_is_hardlinked() {
t/t5607-clone-bundle.sh
+1
@@ -4,6 +4,7 @@ test_description='some bundle related tests'
4
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
5
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
6
7
+TEST_PASSES_SANITIZE_LEAK=true
8
. ./test-lib.sh
9
10
test_expect_success 'setup' '
t/t6020-bundle-misc.sh
+1
@@ -8,6 +8,7 @@ test_description='Test git-bundle'
8
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
9
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
10
11
+TEST_PASSES_SANITIZE_LEAK=true
12
. ./test-lib.sh
13
. "$TEST_DIRECTORY"/lib-bundle.sh
14
. "$TEST_DIRECTORY"/lib-terminal.sh