]> git.ipfire.org Git - thirdparty/git.git/commitdiff
builtin/ls-remote: fix leaking `pattern` strings
authorPatrick Steinhardt <ps@pks.im>
Thu, 1 Aug 2024 10:40:02 +0000 (12:40 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 1 Aug 2024 15:47:36 +0000 (08:47 -0700)
Users can pass patterns to git-ls-remote(1), which allows them to filter
the list of printed references. We assemble those patterns into an array
and prefix them with "*/", but never free either the array nor the
allocated strings.

Refactor the code to use a `struct strvec` instead of manually tracking
the strings in an array. Like this, we can easily use `strvec_clear()`
to release both the vector and the contained string for us, plugging the
leak.

Helped-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/ls-remote.c
t/t5535-fetch-push-symref.sh

index debf2d4f887ed2d24ad0dc8a717ac188c73d5bda..5b61af5d789b543057dff4d83aa3e08fed1d79fd 100644 (file)
@@ -19,17 +19,16 @@ static const char * const ls_remote_usage[] = {
  * Is there one among the list of patterns that match the tail part
  * of the path?
  */
-static int tail_match(const char **pattern, const char *path)
+static int tail_match(const struct strvec *pattern, const char *path)
 {
-       const char *p;
        char *pathbuf;
 
-       if (!pattern)
+       if (!pattern->nr)
                return 1; /* no restriction */
 
        pathbuf = xstrfmt("/%s", path);
-       while ((p = *(pattern++)) != NULL) {
-               if (!wildmatch(p, pathbuf, 0)) {
+       for (size_t i = 0; i < pattern->nr; i++) {
+               if (!wildmatch(pattern->v[i], pathbuf, 0)) {
                        free(pathbuf);
                        return 1;
                }
@@ -47,7 +46,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
        int status = 0;
        int show_symref_target = 0;
        const char *uploadpack = NULL;
-       const char **pattern = NULL;
+       struct strvec pattern = STRVEC_INIT;
        struct transport_ls_refs_options transport_options =
                TRANSPORT_LS_REFS_OPTIONS_INIT;
        int i;
@@ -93,13 +92,8 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
 
        packet_trace_identity("ls-remote");
 
-       if (argc > 1) {
-               int i;
-               CALLOC_ARRAY(pattern, argc);
-               for (i = 1; i < argc; i++) {
-                       pattern[i - 1] = xstrfmt("*/%s", argv[i]);
-               }
-       }
+       for (int i = 1; i < argc; i++)
+               strvec_pushf(&pattern, "*/%s", argv[i]);
 
        if (flags & REF_TAGS)
                strvec_push(&transport_options.ref_prefixes, "refs/tags/");
@@ -136,7 +130,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
                struct ref_array_item *item;
                if (!check_ref_type(ref, flags))
                        continue;
-               if (!tail_match(pattern, ref->name))
+               if (!tail_match(&pattern, ref->name))
                        continue;
                item = ref_array_push(&ref_array, ref->name, &ref->old_oid);
                item->symref = xstrdup_or_null(ref->symref);
@@ -158,5 +152,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
        if (transport_disconnect(transport))
                status = 1;
        transport_ls_refs_options_release(&transport_options);
+
+       strvec_clear(&pattern);
        return status;
 }
index e8f6d233ffb80ba1a449d47df022f7765b12f6af..7122af7fdb50acbd8279617f5741532280135ad8 100755 (executable)
@@ -2,6 +2,7 @@
 
 test_description='avoiding conflicting update through symref aliasing'
 
+TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
 test_expect_success 'setup' '