Fixed a parsing issue in git_prettify_dir_path().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
diff --git a/src/fileops.c b/src/fileops.c
index 5953f26..191aa91 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;
}
- /* 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;
+ end = current;
+ only_dots = 1;
+
+ /* Seek end of path segment */
+ while (end < buffer_end && *end !='/')
+ {
+ only_dots &= (*end == '.');
+ end++;
+ }
- *buffer_out ='\0';
- len = retrieve_previous_path_component_start(buffer_out_start);
- if (len < GIT_SUCCESS)
- return GIT_ERROR;
+ /* Skip current directory */
+ if (only_dots && end == current + 1)
+ {
+ current += 2;
+ continue;
+ }
- buffer_out = (char *)buffer_out_start + len;
- }
+ /* 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;
+ }
- if (current < buffer_end && *current == '/')
- current++;
+ /* Guard against potential multiple dot path traversal (cf http://cwe.mitre.org/data/definitions/33.html) */
+ if (only_dots && end > current)
+ return GIT_ERROR;
- continue;
+ /* Copy to output the path segment */
+ while (current < end)
+ {
+ *buffer_out++ = *current++;
+ len++;
}
- *buffer_out++ = *current++;
+ *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 222e07c..dc2ccc9 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("///", "/"));