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:
parent
58450ffced
commit
bd2e9e66ff
1 changed files with 22 additions and 10 deletions
32
quark.c
32
quark.c
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue