Commit c90292ce by nulltoken Committed by Vicent Marti

Change gitfo_prettify_dir_path() and gitfo_prettify_file_path() behavior

Those functions now return prettified rooted path.
parent 6279abda
...@@ -443,22 +443,29 @@ int gitfo_dirent( ...@@ -443,22 +443,29 @@ int gitfo_dirent(
return GIT_SUCCESS; return GIT_SUCCESS;
} }
#ifdef GIT_WIN32
static int is_windows_rooted_path(const char *path) int retrieve_path_root_offset(const char *path)
{ {
int offset = 0;
#ifdef GIT_WIN32
/* Does the root of the path look like a windows drive ? */ /* Does the root of the path look like a windows drive ? */
if (isalpha(path[0]) && (path[1] == ':')) if (isalpha(path[0]) && (path[1] == ':'))
return GIT_SUCCESS; offset += 2;
#endif
if (*(path + offset) == '/')
return offset;
return GIT_ERROR; return GIT_ERROR;
} }
#endif
int gitfo_mkdir_recurs(const char *path, int mode) int gitfo_mkdir_recurs(const char *path, int mode)
{ {
int error; int error, root_path_offset;
char *pp, *sp; char *pp, *sp;
char *path_copy = git__strdup(path); char *path_copy = git__strdup(path);
...@@ -468,12 +475,9 @@ int gitfo_mkdir_recurs(const char *path, int mode) ...@@ -468,12 +475,9 @@ int gitfo_mkdir_recurs(const char *path, int mode)
error = GIT_SUCCESS; error = GIT_SUCCESS;
pp = path_copy; pp = path_copy;
#ifdef GIT_WIN32 root_path_offset = retrieve_path_root_offset(pp);
if (root_path_offset > 0)
if (!is_windows_rooted_path(pp)) pp += root_path_offset; /* On Windows, will skip the drive name (eg. C: or D:) */
pp += 2; /* Skip the drive name (eg. C: or D:) */
#endif
while (error == GIT_SUCCESS && (sp = strchr(pp, '/')) != 0) { while (error == GIT_SUCCESS && (sp = strchr(pp, '/')) != 0) {
if (sp != pp && gitfo_isdir(path_copy) < GIT_SUCCESS) { if (sp != pp && gitfo_isdir(path_copy) < GIT_SUCCESS) {
...@@ -504,6 +508,8 @@ static int retrieve_previous_path_component_start(const char *path) ...@@ -504,6 +508,8 @@ static int retrieve_previous_path_component_start(const char *path)
len = strlen(path); len = strlen(path);
offset = len - 1; offset = len - 1;
//TODO: Deal with Windows rooted path
/* Skip leading slash */ /* Skip leading slash */
if (path[start] == '/') if (path[start] == '/')
start++; start++;
...@@ -522,15 +528,25 @@ static int retrieve_previous_path_component_start(const char *path) ...@@ -522,15 +528,25 @@ static int retrieve_previous_path_component_start(const char *path)
return offset; return offset;
} }
int gitfo_prettify_dir_path(char *buffer_out, const char *path) int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path)
{ {
int len = 0, segment_len, only_dots; int len = 0, segment_len, only_dots, root_path_offset, error = GIT_SUCCESS;
char *current; char *current;
const char *buffer_out_start, *buffer_end; const char *buffer_out_start, *buffer_end;
buffer_out_start = buffer_out;
current = (char *)path; current = (char *)path;
buffer_end = path + strlen(path); buffer_end = path + strlen(path);
buffer_out_start = buffer_out;
root_path_offset = retrieve_path_root_offset(path);
if (root_path_offset < 0) {
error = gitfo_getcwd(buffer_out, size);
if (error < GIT_SUCCESS)
return error;
len = strlen(buffer_out);
buffer_out += len;
}
while (current < buffer_end) { while (current < buffer_end) {
/* Prevent multiple slashes from being added to the output */ /* Prevent multiple slashes from being added to the output */
...@@ -543,7 +559,7 @@ int gitfo_prettify_dir_path(char *buffer_out, const char *path) ...@@ -543,7 +559,7 @@ int gitfo_prettify_dir_path(char *buffer_out, const char *path)
segment_len = 0; segment_len = 0;
/* Copy path segment to the output */ /* Copy path segment to the output */
while (current < buffer_end && *current !='/') while (current < buffer_end && *current != '/')
{ {
only_dots &= (*current == '.'); only_dots &= (*current == '.');
*buffer_out++ = *current++; *buffer_out++ = *current++;
...@@ -568,7 +584,9 @@ int gitfo_prettify_dir_path(char *buffer_out, const char *path) ...@@ -568,7 +584,9 @@ int gitfo_prettify_dir_path(char *buffer_out, const char *path)
*buffer_out ='\0'; *buffer_out ='\0';
len = retrieve_previous_path_component_start(buffer_out_start); len = retrieve_previous_path_component_start(buffer_out_start);
if (len < GIT_SUCCESS)
/* Are we escaping out of the root dir? */
if (len < 0)
return GIT_EINVALIDPATH; return GIT_EINVALIDPATH;
buffer_out = (char *)buffer_out_start + len; buffer_out = (char *)buffer_out_start + len;
...@@ -576,7 +594,7 @@ int gitfo_prettify_dir_path(char *buffer_out, const char *path) ...@@ -576,7 +594,7 @@ int gitfo_prettify_dir_path(char *buffer_out, const char *path)
} }
/* Guard against potential multiple dot path traversal (cf http://cwe.mitre.org/data/definitions/33.html) */ /* Guard against potential multiple dot path traversal (cf http://cwe.mitre.org/data/definitions/33.html) */
if (only_dots &&segment_len > 0) if (only_dots && segment_len > 0)
return GIT_EINVALIDPATH; return GIT_EINVALIDPATH;
*buffer_out++ = '/'; *buffer_out++ = '/';
...@@ -588,20 +606,24 @@ int gitfo_prettify_dir_path(char *buffer_out, const char *path) ...@@ -588,20 +606,24 @@ int gitfo_prettify_dir_path(char *buffer_out, const char *path)
return GIT_SUCCESS; return GIT_SUCCESS;
} }
int gitfo_prettify_file_path(char *buffer_out, const char *path) int gitfo_prettify_file_path(char *buffer_out, size_t size, const char *path)
{ {
int error, path_len, i; int error, path_len, i;
const char* pattern = "/.."; const char* pattern = "/..";
path_len = strlen(path); path_len = strlen(path);
/* Let's make sure the filename isn't empty nor a dot */
if (path_len == 0 || (path_len == 1 && *path == '.'))
return GIT_EINVALIDPATH;
/* Let's make sure the filename doesn't end with "/", "/." or "/.." */ /* Let's make sure the filename doesn't end with "/", "/." or "/.." */
for (i = 1; path_len > i && i < 4; i++) { for (i = 1; path_len > i && i < 4; i++) {
if (!strncmp(path + path_len - i, pattern, i)) if (!strncmp(path + path_len - i, pattern, i))
return GIT_EINVALIDPATH; return GIT_EINVALIDPATH;
} }
error = gitfo_prettify_dir_path(buffer_out, path); error = gitfo_prettify_dir_path(buffer_out, size, path);
if (error < GIT_SUCCESS) if (error < GIT_SUCCESS)
return error; return error;
......
...@@ -163,12 +163,13 @@ extern int gitfo_getcwd(char *buffer_out, size_t size); ...@@ -163,12 +163,13 @@ extern int gitfo_getcwd(char *buffer_out, size_t size);
* the file system perspective. * the file system perspective.
* *
* @param buffer_out buffer to populate with the normalized path. * @param buffer_out buffer to populate with the normalized path.
* @param size buffer size.
* @param path directory path to clean up. * @param path directory path to clean up.
* @return * @return
* - GIT_SUCCESS on success; * - GIT_SUCCESS on success;
* - GIT_ERROR when the input path is invalid or escapes the current directory. * - GIT_ERROR when the input path is invalid or escapes the current directory.
*/ */
int gitfo_prettify_dir_path(char *buffer_out, const char *path); int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path);
/** /**
* Clean up a provided absolute or relative file path. * Clean up a provided absolute or relative file path.
...@@ -185,11 +186,13 @@ int gitfo_prettify_dir_path(char *buffer_out, const char *path); ...@@ -185,11 +186,13 @@ int gitfo_prettify_dir_path(char *buffer_out, const char *path);
* the file system perspective. * the file system perspective.
* *
* @param buffer_out buffer to populate with the normalized path. * @param buffer_out buffer to populate with the normalized path.
* @param size buffer size.
* @param path file path to clean up. * @param path file path to clean up.
* @return * @return
* - GIT_SUCCESS on success; * - GIT_SUCCESS on success;
* - GIT_ERROR when the input path is invalid or escapes the current directory. * - GIT_ERROR when the input path is invalid or escapes the current directory.
*/ */
int gitfo_prettify_file_path(char *buffer_out, const char *path); int gitfo_prettify_file_path(char *buffer_out, size_t size, const char *path);
int retrieve_path_root_offset(const char *path);
#endif /* INCLUDE_fileops_h__ */ #endif /* INCLUDE_fileops_h__ */
...@@ -66,7 +66,7 @@ static int assign_repository_dirs( ...@@ -66,7 +66,7 @@ static int assign_repository_dirs(
if (git_dir == NULL) if (git_dir == NULL)
return GIT_ENOTFOUND; return GIT_ENOTFOUND;
error = gitfo_prettify_dir_path(path_aux, git_dir); error = gitfo_prettify_dir_path(path_aux, sizeof(path_aux), git_dir);
if (error < GIT_SUCCESS) if (error < GIT_SUCCESS)
return error; return error;
...@@ -81,7 +81,7 @@ static int assign_repository_dirs( ...@@ -81,7 +81,7 @@ static int assign_repository_dirs(
if (git_object_directory == NULL) if (git_object_directory == NULL)
git__joinpath(path_aux, repo->path_repository, GIT_OBJECTS_DIR); git__joinpath(path_aux, repo->path_repository, GIT_OBJECTS_DIR);
else { else {
error = gitfo_prettify_dir_path(path_aux, git_object_directory); error = gitfo_prettify_dir_path(path_aux, sizeof(path_aux), git_object_directory);
if (error < GIT_SUCCESS) if (error < GIT_SUCCESS)
return error; return error;
} }
...@@ -95,7 +95,7 @@ static int assign_repository_dirs( ...@@ -95,7 +95,7 @@ static int assign_repository_dirs(
if (git_work_tree == NULL) if (git_work_tree == NULL)
repo->is_bare = 1; repo->is_bare = 1;
else { else {
error = gitfo_prettify_dir_path(path_aux, git_work_tree); error = gitfo_prettify_dir_path(path_aux, sizeof(path_aux), git_work_tree);
if (error < GIT_SUCCESS) if (error < GIT_SUCCESS)
return error; return error;
...@@ -108,7 +108,7 @@ static int assign_repository_dirs( ...@@ -108,7 +108,7 @@ static int assign_repository_dirs(
if (git_index_file == NULL) if (git_index_file == NULL)
git__joinpath(path_aux, repo->path_repository, GIT_INDEX_FILE); git__joinpath(path_aux, repo->path_repository, GIT_INDEX_FILE);
else { else {
error = gitfo_prettify_file_path(path_aux, git_index_file); error = gitfo_prettify_file_path(path_aux, sizeof(path_aux), git_index_file);
if (error < GIT_SUCCESS) if (error < GIT_SUCCESS)
return error; return error;
} }
...@@ -403,7 +403,7 @@ static int repo_init_find_dir(repo_init *results, const char* path) ...@@ -403,7 +403,7 @@ static int repo_init_find_dir(repo_init *results, const char* path)
char temp_path[GIT_PATH_MAX]; char temp_path[GIT_PATH_MAX];
int error = GIT_SUCCESS; int error = GIT_SUCCESS;
error = gitfo_prettify_dir_path(temp_path, path); error = gitfo_prettify_dir_path(temp_path, sizeof(temp_path), path);
if (error < GIT_SUCCESS) if (error < GIT_SUCCESS)
return error; return error;
......
...@@ -113,22 +113,18 @@ static int ensure_repository_init( ...@@ -113,22 +113,18 @@ static int ensure_repository_init(
return GIT_ERROR; return GIT_ERROR;
if (repo->path_workdir != NULL || expected_working_directory != NULL) { if (repo->path_workdir != NULL || expected_working_directory != NULL) {
if (strcmp(repo->path_workdir, expected_working_directory) != 0) if (git__suffixcmp(repo->path_workdir, expected_working_directory) != 0)
//return GIT_ERROR;
goto cleanup; goto cleanup;
} }
if (strcmp(repo->path_odb, path_odb) != 0) if (git__suffixcmp(repo->path_odb, path_odb) != 0)
//return GIT_ERROR;
goto cleanup; goto cleanup;
if (strcmp(repo->path_repository, expected_path_repository) != 0) if (git__suffixcmp(repo->path_repository, expected_path_repository) != 0)
//return GIT_ERROR;
goto cleanup; goto cleanup;
if (repo->path_index != NULL || expected_path_index != NULL) { if (repo->path_index != NULL || expected_path_index != NULL) {
if (strcmp(repo->path_index, expected_path_index) != 0) if (git__suffixcmp(repo->path_index, expected_path_index) != 0)
//return GIT_ERROR;
goto cleanup; goto cleanup;
} }
...@@ -170,18 +166,18 @@ BEGIN_TEST(init2, "Initialize a bare repo with a relative path escaping out of t ...@@ -170,18 +166,18 @@ BEGIN_TEST(init2, "Initialize a bare repo with a relative path escaping out of t
must_pass(gitfo_getcwd(current_workdir, sizeof(current_workdir))); must_pass(gitfo_getcwd(current_workdir, sizeof(current_workdir)));
git__joinpath(path_repository, current_workdir, "a/b/c/"); git__joinpath(path_repository, TEMP_REPO_FOLDER, "a/b/c/");
must_pass(gitfo_mkdir_recurs(path_repository, mode)); must_pass(gitfo_mkdir_recurs(path_repository, mode));
must_pass(chdir(path_repository)); must_pass(chdir(path_repository));
must_pass(git_repository_init(&repo, "../d/e.git", 1)); must_pass(git_repository_init(&repo, "../d/e.git", 1));
must_pass(git__suffixcmp(repo->path_repository, "/a/b/d/e.git/"));
git_repository_free(repo); git_repository_free(repo);
must_pass(chdir(current_workdir)); must_pass(chdir(current_workdir));
rmdir_recurs(TEMP_REPO_FOLDER);
git__joinpath(path_repository, current_workdir, "a/");
must_pass(rmdir_recurs(path_repository));
END_TEST END_TEST
BEGIN_SUITE(repository) BEGIN_SUITE(repository)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment