]> git.ipfire.org Git - thirdparty/git.git/commitdiff
bundle: plug leaks in `create_bundle()`
authorPatrick Steinhardt <ps@pks.im>
Tue, 11 Jun 2024 09:19:31 +0000 (11:19 +0200)
committerJunio C Hamano <gitster@pobox.com>
Tue, 11 Jun 2024 20:15:05 +0000 (13:15 -0700)
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>
bundle.c
t/t5605-clone-local.sh
t/t5607-clone-bundle.sh
t/t6020-bundle-misc.sh

index 95367c2d0a06dd69cc36114ebae5a28aab8a9700..9af558c7a9b9d4c3575bc97f7658b525b3a762ef 100644 (file)
--- 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,
index a3055869bc7bc182e2e4af736b06785ee28bed85..9a1390a98fb95f121c6e0bc75ab0320491b27bb6 100755 (executable)
@@ -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() {
index 0d1e92d9963554323a0e9a3891e43eeb263b1aff..ac5ce9b648a7f5d48ee62ee0724310d9e3f68363 100755 (executable)
@@ -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' '
index 3e6bcbf30cdaf0e623ae73858a4f98838e03255c..fe75a06572aed63c2227398de9f82c8006b8e1e7 100755 (executable)
@@ -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