From ae7ffea96132ee8df08f7c18aac6b36acbd689cf Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sat, 22 Jan 2011 14:04:32 +0100 Subject: [PATCH] Fixed a parsing issue in git_prettify_dir_path(). --- src/fileops.c | 69 +++++++++++++++++++++++++++------------------- tests/t0005-path.c | 10 ++++++- 2 files changed, 50 insertions(+), 29 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 5953f26f6..191aa91fa 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -394,8 +394,9 @@ static int retrieve_previous_path_component_start(const char *path) int git_prettify_dir_path(char *buffer_out, const char *path) { int len = 0; - char *current; + char *current, *end; const char *buffer_out_start, *buffer_end; + int only_dots; buffer_out_start = buffer_out; current = (char *)path; @@ -408,40 +409,52 @@ int git_prettify_dir_path(char *buffer_out, const char *path) continue; } + end = current; + only_dots = 1; + + /* Seek end of path segment */ + while (end < buffer_end && *end !='/') + { + only_dots &= (*end == '.'); + end++; + } + /* Skip current directory */ - if (*current == '.') { - current++; - - /* Handle the double-dot upward directory navigation */ - if (current < buffer_end && *current == '.') { - current++; - - /* Guard against potential multiple dot path traversal (cf http://cwe.mitre.org/data/definitions/33.html) */ - if (*current == '.') - return GIT_ERROR; - - *buffer_out ='\0'; - len = retrieve_previous_path_component_start(buffer_out_start); - if (len < GIT_SUCCESS) - return GIT_ERROR; - - buffer_out = (char *)buffer_out_start + len; - } - - if (current < buffer_end && *current == '/') - current++; - + if (only_dots && end == current + 1) + { + current += 2; continue; } - *buffer_out++ = *current++; + /* Handle the double-dot upward directory navigation */ + if (only_dots && end == current + 2) + { + *buffer_out ='\0'; + len = retrieve_previous_path_component_start(buffer_out_start); + if (len < GIT_SUCCESS) + return GIT_ERROR; + + buffer_out = (char *)buffer_out_start + len; + + current += 3; + continue; + } + + /* Guard against potential multiple dot path traversal (cf http://cwe.mitre.org/data/definitions/33.html) */ + if (only_dots && end > current) + return GIT_ERROR; + + /* Copy to output the path segment */ + while (current < end) + { + *buffer_out++ = *current++; + len++; + } + + *buffer_out++ = '/'; len++; } - /* Add a trailing slash if required */ - if (len > 0 && buffer_out_start[len-1] != '/') - *buffer_out++ = '/'; - *buffer_out = '\0'; return GIT_SUCCESS; diff --git a/tests/t0005-path.c b/tests/t0005-path.c index 222e07c2d..dc2ccc916 100644 --- a/tests/t0005-path.c +++ b/tests/t0005-path.c @@ -20,6 +20,10 @@ static int ensure_normalized(const char *input_path, const char *expected_path) } BEGIN_TEST(path_prettifying) + must_pass(ensure_normalized("./testrepo.git", "testrepo.git/")); + must_pass(ensure_normalized("./.git", ".git/")); + must_pass(ensure_normalized("./git.", "git./")); + must_pass(ensure_normalized("git./", "git./")); must_pass(ensure_normalized("", "")); must_pass(ensure_normalized(".", "")); must_pass(ensure_normalized("./", "")); @@ -53,7 +57,11 @@ BEGIN_TEST(path_prettifying) must_fail(ensure_normalized("d1/...", NULL)); must_fail(ensure_normalized("d1/.../", NULL)); must_fail(ensure_normalized("d1/.../d2", NULL)); - + + must_pass(ensure_normalized("/./testrepo.git", "/testrepo.git/")); + must_pass(ensure_normalized("/./.git", "/.git/")); + must_pass(ensure_normalized("/./git.", "/git./")); + must_pass(ensure_normalized("/git./", "/git./")); must_pass(ensure_normalized("/", "/")); must_pass(ensure_normalized("//", "/")); must_pass(ensure_normalized("///", "/"));