diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 9fa616fb0..a325d1327 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -546,11 +546,21 @@ static int validate_ownership_cb(const git_config_entry *entry, void *payload) { validate_ownership_data *data = payload; + /* Empty value means stop processing and disallow. */ if (strcmp(entry->value, "") == 0) { *data->is_safe = false; - } else if (strcmp(entry->value, "*") == 0) { + } + + /* Wildcard value disables the silly ownership checks. */ + else if (strcmp(entry->value, "*") == 0) { *data->is_safe = true; - } else { + } + + /* + * Otherwise, the config value *must not* end with a trailing + * slash for git compatibility. + */ + else if (git__suffixcmp(entry->value, "/") != 0) { const char *test_path = entry->value; #ifdef GIT_WIN32 diff --git a/tests/libgit2/repo/open.c b/tests/libgit2/repo/open.c index 3d1a0620b..b57b65713 100644 --- a/tests/libgit2/repo/open.c +++ b/tests/libgit2/repo/open.c @@ -578,6 +578,51 @@ void test_repo_open__can_allowlist_dirs_with_problematic_ownership(void) git_str_dispose(&config_data); } +void test_repo_open__ownership_allowlist_cannot_have_trailing_slash(void) +{ + git_repository *repo; + git_str config_path = GIT_STR_INIT, + config_filename = GIT_STR_INIT, + config_data = GIT_STR_INIT; + + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1)); + + cl_fixture_sandbox("empty_standard_repo"); + cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git")); + + git_fs_path__set_owner(GIT_FS_PATH_OWNER_OTHER); + cl_git_fail_with(GIT_EOWNER, git_repository_open(&repo, "empty_standard_repo")); + + /* Add safe.directory options to the global configuration */ + git_str_joinpath(&config_path, clar_sandbox_path(), "__global_config"); + cl_must_pass(p_mkdir(config_path.ptr, 0777)); + git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, config_path.ptr); + + git_str_joinpath(&config_filename, config_path.ptr, ".gitconfig"); + + git_str_printf(&config_data, + "[foo]\n" \ + "\tbar = Foobar\n" \ + "\tbaz = Baz!\n" \ + "[safe]\n" \ + "\tdirectory = /non/existent/path\n" \ + "\tdirectory = /\n" \ + "\tdirectory = c:\\\\temp\n" \ + "\tdirectory = %s/%s/\n" \ + "\tdirectory = /tmp\n" \ + "[bar]\n" \ + "\tfoo = barfoo\n", + clar_sandbox_path(), "empty_standard_repo"); + cl_git_rewritefile(config_filename.ptr, config_data.ptr); + + cl_git_fail(git_repository_open(&repo, "empty_standard_repo")); + git_repository_free(repo); + + git_str_dispose(&config_path); + git_str_dispose(&config_filename); + git_str_dispose(&config_data); +} + void test_repo_open__can_wildcard_allowlist_with_problematic_ownership(void) { git_repository *repo;