diff options
author | Nikolai Vladimirov <nikolay@vladimiroff.com> | 2013-09-03 07:58:21 +0300 |
---|---|---|
committer | Nikolai Vladimirov <nikolay@vladimiroff.com> | 2013-09-03 20:45:53 +0300 |
commit | 6d9a6c5cecebfaaecb4c39d002c8e0cdd26c4b85 (patch) | |
tree | 935ac5d8d0888fe0824b3eb35ebe5a2d293512ba /src/path.c | |
parent | c46fe0c651c9dc32ba03fab5b34340d92af864e6 (diff) | |
download | libgit2-6d9a6c5cecebfaaecb4c39d002c8e0cdd26c4b85.tar.gz |
path: properly resolve relative paths
Diffstat (limited to 'src/path.c')
-rw-r--r-- | src/path.c | 31 |
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) |