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 /.
This commit is contained in:
Laslo Hunhold 2017-06-21 11:02:35 +02:00
parent 58450ffced
commit bd2e9e66ff

32
quark.c
View file

@ -460,8 +460,8 @@ static int
normabspath(char *path) normabspath(char *path)
{ {
size_t len; size_t len;
int done = 0; int last = 0;
char *p, *q, *lastp; char *p, *q;
/* require and skip first slash */ /* require and skip first slash */
if (path[0] != '/') { if (path[0] != '/') {
@ -472,25 +472,37 @@ normabspath(char *path)
/* get length of path */ /* get length of path */
len = strlen(p); len = strlen(p);
for (lastp = p; !done; ) { for (; !last; ) {
/* bound path component within (p,q) */ /* bound path component within (p,q) */
if (!(q = strchr(p, '/'))) { if (!(q = strchr(p, '/'))) {
q = strchr(p, '\0'); q = strchr(p, '\0');
done = 1; last = 1;
} }
if (p == q || (q - p == 1 && p[0] == '.')) { if (p == q || (q - p == 1 && p[0] == '.')) {
/* "/" or "./" */ /* "/" or "./" */
memcpy(p, q + 1, len - ((q + 1) - path) + 2); goto squash;
len -= (q + 1) - p;
} else if (q - p == 2 && p[0] == '.' && p[1] == '.') { } else if (q - p == 2 && p[0] == '.' && p[1] == '.') {
/* "../" */ /* "../" */
memcpy(lastp, q + 1, len - ((q + 1) - path) + 2); if (p != path + 1) {
len -= (q + 1) - lastp; /* place p right after the previous / */
p = lastp; for (p -= 2; p > path && *p != '/'; p--);
p++;
}
goto squash;
} else { } else {
lastp = p; /* move on */
p = q + 1; 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;
} }
} }