]> git.ipfire.org Git - thirdparty/git.git/commitdiff
transport: also free remote_refs in transport_disconnect()
authorAndrzej Hunt <ajrhunt@google.com>
Sun, 21 Mar 2021 16:58:37 +0000 (16:58 +0000)
committerJunio C Hamano <gitster@pobox.com>
Sun, 21 Mar 2021 21:39:10 +0000 (14:39 -0700)
transport_get_remote_refs() can populate the transport struct's
remote_refs. transport_disconnect() is already responsible for most of
transport's cleanup - therefore we also take care of freeing remote_refs
there.

There are 2 locations where transport_disconnect() is called before
we're done using the returned remote_refs. This patch changes those
callsites to only call transport_disconnect() after the returned refs
are no longer being used - which is necessary to safely be able to
free remote_refs during transport_disconnect().

This commit fixes the following leak which was found while running
t0000, but is expected to also fix the same pattern of leak in all
locations that use transport_get_remote_refs():

Direct leak of 165 byte(s) in 1 object(s) allocated from:
    #0 0x49a6b2 in calloc /home/abuild/rpmbuild/BUILD/llvm-11.0.0.src/build/../projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:154:3
    #1 0x9a72f2 in xcalloc /home/ahunt/oss-fuzz/git/wrapper.c:140:8
    #2 0x8ce203 in alloc_ref_with_prefix /home/ahunt/oss-fuzz/git/remote.c:867:20
    #3 0x8ce1a2 in alloc_ref /home/ahunt/oss-fuzz/git/remote.c:875:9
    #4 0x72f63e in process_ref_v2 /home/ahunt/oss-fuzz/git/connect.c:426:8
    #5 0x72f21a in get_remote_refs /home/ahunt/oss-fuzz/git/connect.c:525:8
    #6 0x979ab7 in handshake /home/ahunt/oss-fuzz/git/transport.c:305:4
    #7 0x97872d in get_refs_via_connect /home/ahunt/oss-fuzz/git/transport.c:339:9
    #8 0x9774b5 in transport_get_remote_refs /home/ahunt/oss-fuzz/git/transport.c:1388:4
    #9 0x51cf80 in cmd_clone /home/ahunt/oss-fuzz/git/builtin/clone.c:1271:9
    #10 0x4cd60d in run_builtin /home/ahunt/oss-fuzz/git/git.c:453:11
    #11 0x4cb2da in handle_builtin /home/ahunt/oss-fuzz/git/git.c:704:3
    #12 0x4ccc37 in run_argv /home/ahunt/oss-fuzz/git/git.c:771:4
    #13 0x4cac29 in cmd_main /home/ahunt/oss-fuzz/git/git.c:902:19
    #14 0x69c45e in main /home/ahunt/oss-fuzz/git/common-main.c:52:11
    #15 0x7f6a459d5349 in __libc_start_main (/lib64/libc.so.6+0x24349)

Signed-off-by: Andrzej Hunt <ajrhunt@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/ls-remote.c
builtin/remote.c
transport.c

index ef604752a044a48609a10ee90a8ca487c0acfb2d..5432d239a681e212a0b60027172ff89f4be17f1e 100644 (file)
@@ -124,8 +124,6 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
                int hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
                repo_set_hash_algo(the_repository, hash_algo);
        }
-       if (transport_disconnect(transport))
-               return 1;
 
        if (!dest && !quiet)
                fprintf(stderr, "From %s\n", *remote->url);
@@ -151,5 +149,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
        }
 
        ref_array_clear(&ref_array);
+       if (transport_disconnect(transport))
+               return 1;
        return status;
 }
index d11a5589e49dcc9ea06663c422154855f9ad529b..e31d9c99470e8e38c7b0ffe0611f1f51ace1c1af 100644 (file)
@@ -938,9 +938,6 @@ static int get_remote_ref_states(const char *name,
                                 struct ref_states *states,
                                 int query)
 {
-       struct transport *transport;
-       const struct ref *remote_refs;
-
        states->remote = remote_get(name);
        if (!states->remote)
                return error(_("No such remote: '%s'"), name);
@@ -948,10 +945,12 @@ static int get_remote_ref_states(const char *name,
        read_branches();
 
        if (query) {
+               struct transport *transport;
+               const struct ref *remote_refs;
+
                transport = transport_get(states->remote, states->remote->url_nr > 0 ?
                        states->remote->url[0] : NULL);
                remote_refs = transport_get_remote_refs(transport, NULL);
-               transport_disconnect(transport);
 
                states->queried = 1;
                if (query & GET_REF_STATES)
@@ -960,6 +959,7 @@ static int get_remote_ref_states(const char *name,
                        get_head_names(remote_refs, states);
                if (query & GET_PUSH_REF_STATES)
                        get_push_ref_states(remote_refs, states);
+               transport_disconnect(transport);
        } else {
                for_each_ref(append_ref_to_tracked_list, states);
                string_list_sort(&states->tracked);
index b13fab5dc3b1b90933b77f15fe87ca422cc70784..62362d79dd876a47a223ab5903d5c26d99ad09ea 100644 (file)
@@ -1452,6 +1452,8 @@ int transport_disconnect(struct transport *transport)
        int ret = 0;
        if (transport->vtable->disconnect)
                ret = transport->vtable->disconnect(transport);
+       if (transport->got_remote_refs)
+               free_refs((void *)transport->remote_refs);
        free(transport);
        return ret;
 }