builtin/init-db: handle bare clones when core.bare set to false

In 552955ed7f ("clone: use more conventional config/option layering", 2020-10-01), clone learned to read configuration options earlier in its execution, before creating the new repository. However, that led to a problem: if the core.bare setting is set to false in the global config, cloning a bare repository segfaults. This happens because the repository is falsely thought to be non-bare, but clone has set the work tree to NULL, which is then dereferenced. The code to initialize the repository already considers the fact that a user might want to override the --bare option for git init, but it doesn't take into account clone, which uses a different option. Let's just check that the work tree is not NULL, since that's how clone indicates that the repository is bare. This is also the case for git init, so we won't be regressing that case. Reported-by: Joseph Vusich <jvusich@amazon.com> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

brian m. carlson committed Mar 10, 2021 at 01:11 UTC 75555676ad3908b0f847a9ae154c35e12114c82f
2 files changed +10 -2
builtin/init-db.c
+2 -2
@@ -212,6 +212,7 @@ static int create_default_files(const char *template_path,
212 int reinit;
213 int filemode;
214 struct strbuf err = STRBUF_INIT;
215 + const char *work_tree = get_git_work_tree();
216
217 /* Just look for `init.templatedir` */
218 init_db_template_dir = NULL; /* re-set in case it was set before */
@@ -235,7 +236,7 @@ static int create_default_files(const char *template_path,
236 * We must make sure command-line options continue to override any
237 * values we might have just re-read from the config.
238 */
238 - is_bare_repository_cfg = init_is_bare_repository;
239 + is_bare_repository_cfg = init_is_bare_repository || !work_tree;
240 if (init_shared_repository != -1)
241 set_shared_repository(init_shared_repository);
242
@@ -299,7 +300,6 @@ static int create_default_files(const char *template_path,
300 if (is_bare_repository())
301 git_config_set("core.bare", "true");
302 else {
302 - const char *work_tree = get_git_work_tree();
303 git_config_set("core.bare", "false");
304 /* allow template config file to override the default */
305 if (log_all_ref_updates == LOG_REFS_UNSET)
t/t5606-clone-options.sh
+8
@@ -101,6 +101,14 @@ test_expect_success 'redirected clone -v does show progress' '
101
102 '
103
104 +test_expect_success 'clone does not segfault with --bare and core.bare=false' '
105 + test_config_global core.bare false &&
106 + git clone --bare parent clone-bare &&
107 + echo true >expect &&
108 + git -C clone-bare rev-parse --is-bare-repository >actual &&
109 + test_cmp expect actual
110 +'
111 +
112 test_expect_success 'chooses correct default initial branch name' '
113 git init --bare empty &&
114 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \