quark

quark web server
git clone git://git.suckless.org/quark
Log | Files | Refs | LICENSE

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:
Mquark.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; } }