Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolai Vladimirov <nikolay@vladimiroff.com>2013-09-03 08:58:21 +0400
committerNikolai Vladimirov <nikolay@vladimiroff.com>2013-09-03 21:45:53 +0400
commit6d9a6c5cecebfaaecb4c39d002c8e0cdd26c4b85 (patch)
tree935ac5d8d0888fe0824b3eb35ebe5a2d293512ba /src/path.c
parentc46fe0c651c9dc32ba03fab5b34340d92af864e6 (diff)
path: properly resolve relative paths
Diffstat (limited to 'src/path.c')
-rw-r--r--src/path.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/src/path.c b/src/path.c
index a753a734d..50a990b27 100644
--- a/src/path.c
+++ b/src/path.c
@@ -646,12 +646,33 @@ int git_path_resolve_relative(git_buf *path, size_t ceiling)
/* do nothing with singleton dot */;
else if (len == 2 && from[0] == '.' && from[1] == '.') {
- while (to > base && to[-1] == '/') to--;
- while (to > base && to[-1] != '/') to--;
- }
+ /* error out if trying to up one from a hard base */
+ if (to == base && ceiling != 0) {
+ giterr_set(GITERR_INVALID,
+ "Cannot strip root component off url");
+ return -1;
+ }
+
+ /* no more path segments to strip,
+ * use '../' as a new base path */
+ if (to == base) {
+ if (*next == '/')
+ len++;
- else {
- if (*next == '/')
+ if (to != from)
+ memmove(to, from, len);
+
+ to += len;
+ /* this is now the base, can't back up from a
+ * relative prefix */
+ base = to;
+ } else {
+ /* back up a path segment */
+ while (to > base && to[-1] == '/') to--;
+ while (to > base && to[-1] != '/') to--;
+ }
+ } else {
+ if (*next == '/' && *from != '/')
len++;
if (to != from)