]> git.ipfire.org Git - thirdparty/git.git/commitdiff
builtin/submodule--helper.c: handle missing submodule URLs
authorTaylor Blau <me@ttaylorr.com>
Wed, 24 May 2023 19:51:43 +0000 (15:51 -0400)
committerJunio C Hamano <gitster@pobox.com>
Wed, 24 May 2023 20:26:59 +0000 (05:26 +0900)
In e0a862fdaf (submodule helper: convert relative URL to absolute URL if
needed, 2018-10-16), `prepare_to_clone_next_submodule()` lost the
ability to handle URL-less submodules, due to a change from:

    if (repo_get_config_string_const(the_repostiory, sb.buf, &url))
        url = sub->url;

to

    if (repo_get_config_string_const(the_repostiory, sb.buf, &url)) {
        if (starts_with_dot_slash(sub->url) ||
            starts_with_dot_dot_slash(sub->url)) {
                /* ... */
            }
    }

, which will segfault when `sub->url` is NULL, since both
`starts_with_dot_slash()` does not guard its arguments as non-NULL.

Guard the checks to both of the above functions by first checking
whether `sub->url` is non-NULL. There is no need to check whether `sub`
itself is NULL, since we already perform this check earlier in
`prepare_to_clone_next_submodule()`.

By adding a NULL-ness check on `sub->url`, we'll fall into the 'else'
branch, setting `url` to `sub->url` (which is NULL). Before attempting
to invoke `git submodule--helper clone`, check whether `url` is NULL,
and die() if it is.

Reported-by: Tribo Dar <3bodar@gmail.com>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/submodule--helper.c
t/t7400-submodule-basic.sh

index 4c173d8b37adfc72ec840fd88ca27e36f432aef3..4c857950c5ce133a7522bc7838cc79e29c61f2ae 100644 (file)
@@ -2016,14 +2016,17 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
        strbuf_reset(&sb);
        strbuf_addf(&sb, "submodule.%s.url", sub->name);
        if (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {
-               if (starts_with_dot_slash(sub->url) ||
-                   starts_with_dot_dot_slash(sub->url)) {
+               if (sub->url && (starts_with_dot_slash(sub->url) ||
+                                starts_with_dot_dot_slash(sub->url))) {
                        url = resolve_relative_url(sub->url, NULL, 0);
                        need_free_url = 1;
                } else
                        url = sub->url;
        }
 
+       if (!url)
+               die(_("cannot clone submodule '%s' without a URL"), sub->name);
+
        strbuf_reset(&sb);
        strbuf_addf(&sb, "%s/.git", ce->name);
        needs_cloning = !file_exists(sb.buf);
index eae6a46ef3d89f2563d5ec69f83dfd2ad6e7829f..d9fbabb2b9d810d0c39cd504d105bcb8ba3e568c 100755 (executable)
@@ -1351,6 +1351,22 @@ test_expect_success 'clone active submodule without submodule url set' '
        )
 '
 
+test_expect_success 'update submodules without url set in .gitconfig' '
+       test_when_finished "rm -rf multisuper_clone" &&
+       git clone file://"$pwd"/multisuper multisuper_clone &&
+
+       git -C multisuper_clone submodule init &&
+       for s in sub0 sub1 sub2 sub3
+       do
+               key=submodule.$s.url &&
+               git -C multisuper_clone config --local --unset $key &&
+               git -C multisuper_clone config --file .gitmodules --unset $key || return 1
+       done &&
+
+       test_must_fail git -C multisuper_clone submodule update 2>err &&
+       grep "cannot clone submodule .sub[0-3]. without a URL" err
+'
+
 test_expect_success 'clone --recurse-submodules with a pathspec works' '
        test_when_finished "rm -rf multisuper_clone" &&
        cat >expected <<-\EOF &&