From 86a8cd9f6a039889801b5bec865a4bc3deb30f47 Mon Sep 17 00:00:00 2001 From: Sven Strickroth2 Date: Mon, 20 Mar 2017 11:21:00 +0100 Subject: [PATCH 1/2] filebuf: fix resolving absolute symlinks The symlink destination is always concatenated to the original path. Fix this by using `git_buf_sets` instead of `git_buf_puts`. --- src/filebuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filebuf.c b/src/filebuf.c index ef68b16f4..825b9c04c 100644 --- a/src/filebuf.c +++ b/src/filebuf.c @@ -246,7 +246,7 @@ static int resolve_symlink(git_buf *out, const char *path) root = git_path_root(target.ptr); if (root >= 0) { - if ((error = git_buf_puts(&curpath, target.ptr)) < 0) + if ((error = git_buf_sets(&curpath, target.ptr)) < 0) goto cleanup; } else { git_buf dir = GIT_BUF_INIT; From c10ce7c21a6f48839b118a0ff7417d9d75920ee7 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 20 Mar 2017 12:11:05 +0100 Subject: [PATCH 2/2] tests: filebuf: test writing to symlink with absolute paths --- tests/core/filebuf.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/core/filebuf.c b/tests/core/filebuf.c index 04a380b20..ef7ac6bd9 100644 --- a/tests/core/filebuf.c +++ b/tests/core/filebuf.c @@ -187,6 +187,35 @@ void test_core_filebuf__symlink_follow(void) cl_git_pass(git_futils_rmdir_r(dir, NULL, GIT_RMDIR_REMOVE_FILES)); } +void test_core_filebuf__symlink_follow_absolute_paths(void) +{ + git_filebuf file = GIT_FILEBUF_INIT; + git_buf source = GIT_BUF_INIT, target = GIT_BUF_INIT; + +#ifdef GIT_WIN32 + cl_skip(); +#endif + + cl_git_pass(git_buf_joinpath(&source, clar_sandbox_path(), "linkdir/link")); + cl_git_pass(git_buf_joinpath(&target, clar_sandbox_path(), "linkdir/target")); + cl_git_pass(p_mkdir("linkdir", 0777)); + cl_git_pass(p_symlink(target.ptr, source.ptr)); + + cl_git_pass(git_filebuf_open(&file, source.ptr, 0, 0666)); + cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks")); + + cl_assert_equal_i(true, git_path_exists("linkdir/target.lock")); + + cl_git_pass(git_filebuf_commit(&file)); + cl_assert_equal_i(true, git_path_exists("linkdir/target")); + + git_filebuf_cleanup(&file); + git_buf_free(&source); + git_buf_free(&target); + + cl_git_pass(git_futils_rmdir_r("linkdir", NULL, GIT_RMDIR_REMOVE_FILES)); +} + void test_core_filebuf__symlink_depth(void) { git_filebuf file = GIT_FILEBUF_INIT;