summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2024-06-11 11:19:31 +0200
committerJunio C Hamano <gitster@pobox.com>2024-06-11 22:15:05 +0200
commit11ee9a75e7d6f149431f69400c81006f8ccecad5 (patch)
tree4f68bf6d6779a8f94d77b75bbd39cf1bcc5b40f3
parentnotes-utils: free note trees when releasing copied notes (diff)
downloadgit-11ee9a75e7d6f149431f69400c81006f8ccecad5.tar.xz
git-11ee9a75e7d6f149431f69400c81006f8ccecad5.zip
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>
-rw-r--r--bundle.c29
-rwxr-xr-xt/t5605-clone-local.sh1
-rwxr-xr-xt/t5607-clone-bundle.sh1
-rwxr-xr-xt/t6020-bundle-misc.sh1
4 files changed, 22 insertions, 10 deletions
diff --git a/bundle.c b/bundle.c
index 95367c2d0a..9af558c7a9 100644
--- a/bundle.c
+++ b/bundle.c
@@ -500,6 +500,7 @@ int create_bundle(struct repository *r, const char *path,
struct rev_info revs, revs_copy;
int min_version = 2;
struct bundle_prerequisites_info bpi;
+ int ret;
int i;
/* init revs to list objects for pack-objects later */
@@ -525,8 +526,8 @@ int create_bundle(struct repository *r, const char *path,
min_version = 3;
if (argc > 1) {
- error(_("unrecognized argument: %s"), argv[1]);
- goto err;
+ ret = error(_("unrecognized argument: %s"), argv[1]);
+ goto out;
}
bundle_to_stdout = !strcmp(path, "-");
@@ -591,23 +592,31 @@ int create_bundle(struct repository *r, const char *path,
/* write bundle refs */
ref_count = write_bundle_refs(bundle_fd, &revs_copy);
- if (!ref_count)
+ if (!ref_count) {
die(_("Refusing to create empty bundle."));
- else if (ref_count < 0)
- goto err;
+ } else if (ref_count < 0) {
+ ret = -1;
+ goto out;
+ }
/* write pack */
- if (write_pack_data(bundle_fd, &revs_copy, pack_options))
- goto err;
+ if (write_pack_data(bundle_fd, &revs_copy, pack_options)) {
+ ret = -1;
+ goto out;
+ }
if (!bundle_to_stdout) {
if (commit_lock_file(&lock))
die_errno(_("cannot create '%s'"), path);
}
- return 0;
-err:
+
+ ret = 0;
+
+out:
+ object_array_clear(&revs_copy.pending);
+ release_revisions(&revs);
rollback_lock_file(&lock);
- return -1;
+ return ret;
}
int unbundle(struct repository *r, struct bundle_header *header,
diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh
index a3055869bc..9a1390a98f 100755
--- a/t/t5605-clone-local.sh
+++ b/t/t5605-clone-local.sh
@@ -4,6 +4,7 @@ test_description='test local clone'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
repo_is_hardlinked() {
diff --git a/t/t5607-clone-bundle.sh b/t/t5607-clone-bundle.sh
index 0d1e92d996..ac5ce9b648 100755
--- a/t/t5607-clone-bundle.sh
+++ b/t/t5607-clone-bundle.sh
@@ -4,6 +4,7 @@ test_description='some bundle related tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh
index 3e6bcbf30c..fe75a06572 100755
--- a/t/t6020-bundle-misc.sh
+++ b/t/t6020-bundle-misc.sh
@@ -8,6 +8,7 @@ test_description='Test git-bundle'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-bundle.sh
. "$TEST_DIRECTORY"/lib-terminal.sh