Commit 83a1e614fa4435d8708792202e4f2f2c0b3ce51f

Edward Thomson 2022-01-05T09:18:59

config: handle empty conditional in includeIf When a config file contains `[includeIf]` (with no condition), we should treat that as a falsey value. This means that we should properly parse a config value of `includeIf.path`.

diff --git a/src/config_file.c b/src/config_file.c
index 11b4440..91446df 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -724,14 +724,23 @@ static const struct {
 static int parse_conditional_include(config_file_parse_data *parse_data, const char *section, const char *file)
 {
 	char *condition;
-	size_t i;
+	size_t section_len, i;
 	int error = 0, matches;
 
 	if (!parse_data->repo || !file)
 		return 0;
 
-	condition = git__substrdup(section + strlen("includeIf."),
-				   strlen(section) - strlen("includeIf.") - strlen(".path"));
+	section_len = strlen(section);
+
+	/*
+	 * We checked that the string starts with `includeIf.` and ends
+	 * in `.path` to get here.  Make sure it consists of more.
+	 */
+	if (section_len < CONST_STRLEN("includeIf.") + CONST_STRLEN(".path"))
+		return 0;
+
+	condition = git__substrdup(section + CONST_STRLEN("includeIf."),
+				   section_len - CONST_STRLEN("includeIf.") - CONST_STRLEN(".path"));
 
 	for (i = 0; i < ARRAY_SIZE(conditions); i++) {
 		if (git__prefixcmp(condition, conditions[i].prefix))
diff --git a/tests/config/conditionals.c b/tests/config/conditionals.c
index 6249dbd..564719d 100644
--- a/tests/config/conditionals.c
+++ b/tests/config/conditionals.c
@@ -148,3 +148,28 @@ void test_config_conditionals__onbranch(void)
 	assert_condition_includes("onbranch", "dir*", false);
 	assert_condition_includes("onbranch", "dir/*", false);
 }
+
+void test_config_conditionals__empty(void)
+{
+	git_buf value = GIT_BUF_INIT;
+	git_str buf = GIT_STR_INIT;
+	git_config *cfg;
+
+	cl_git_pass(git_str_puts(&buf, "[includeIf]\n"));
+	cl_git_pass(git_str_puts(&buf, "path = other\n"));
+
+	cl_git_mkfile("empty_standard_repo/.git/config", buf.ptr);
+	cl_git_mkfile("empty_standard_repo/.git/other", "[foo]\nbar=baz\n");
+	_repo = cl_git_sandbox_reopen();
+
+	git_str_dispose(&buf);
+
+	cl_git_pass(git_repository_config(&cfg, _repo));
+
+	cl_git_fail_with(GIT_ENOTFOUND,
+		git_config_get_string_buf(&value, cfg, "foo.bar"));
+
+	git_str_dispose(&buf);
+	git_buf_dispose(&value);
+	git_config_free(cfg);
+}