commit bd2e9e66ffda25e583b2978d1f84163b15f301db
parent 58450ffced8b75dd4e8e6e61b2753ee16126e26a
Author: Laslo Hunhold <dev@frign.de>
Date: Wed, 21 Jun 2017 11:02:35 +0200
Fix normabspath() to handle consecutive '..'s properly
The approach with lastp only works if we only go back one dir at a time.
Of course, this cannot be assumed, so we traverse the path backwards
looking for the previous /.
Diffstat:
M | quark.c | | | 32 | ++++++++++++++++++++++---------- |
1 file changed, 22 insertions(+), 10 deletions(-)
diff --git a/quark.c b/quark.c
@@ -460,8 +460,8 @@ static int
normabspath(char *path)
{
size_t len;
- int done = 0;
- char *p, *q, *lastp;
+ int last = 0;
+ char *p, *q;
/* require and skip first slash */
if (path[0] != '/') {
@@ -472,25 +472,37 @@ normabspath(char *path)
/* get length of path */
len = strlen(p);
- for (lastp = p; !done; ) {
+ for (; !last; ) {
/* bound path component within (p,q) */
if (!(q = strchr(p, '/'))) {
q = strchr(p, '\0');
- done = 1;
+ last = 1;
}
if (p == q || (q - p == 1 && p[0] == '.')) {
/* "/" or "./" */
- memcpy(p, q + 1, len - ((q + 1) - path) + 2);
- len -= (q + 1) - p;
+ goto squash;
} else if (q - p == 2 && p[0] == '.' && p[1] == '.') {
/* "../" */
- memcpy(lastp, q + 1, len - ((q + 1) - path) + 2);
- len -= (q + 1) - lastp;
- p = lastp;
+ if (p != path + 1) {
+ /* place p right after the previous / */
+ for (p -= 2; p > path && *p != '/'; p--);
+ p++;
+ }
+ goto squash;
} else {
- lastp = p;
+ /* move on */
p = q + 1;
+ continue;
+ }
+squash:
+ /* squash (p,q) into void */
+ if (last) {
+ *p = '\0';
+ len = p - path;
+ } else {
+ memcpy(p, q + 1, len - ((q + 1) - path) + 2);
+ len -= (q + 1) - p;
}
}