summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/httpd.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/networking/httpd.c b/networking/httpd.c
index 0356e4c..f52785b 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -2012,30 +2012,36 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
/* Algorithm stolen from libbb bb_simplify_path(),
* but don't strdup, retain trailing slash, protect root */
urlp = tptr = urlcopy;
- do {
+ for (;;) {
if (*urlp == '/') {
/* skip duplicate (or initial) slash */
if (*tptr == '/') {
- continue;
+ goto next_char;
}
if (*tptr == '.') {
- /* skip extra "/./" */
- if (tptr[1] == '/' || !tptr[1]) {
- continue;
- }
- /* "..": be careful */
- if (tptr[1] == '.' && (tptr[2] == '/' || !tptr[2])) {
- ++tptr;
- if (urlp == urlcopy) /* protect root */
+ if (tptr[1] == '.' && (tptr[2] == '/' || tptr[2] == '\0')) {
+ /* "..": be careful */
+ /* protect root */
+ if (urlp == urlcopy)
send_headers_and_exit(HTTP_BAD_REQUEST);
- while (*--urlp != '/') /* omit previous dir */;
+ /* omit previous dir */
+ while (*--urlp != '/')
continue;
+ /* skip to "./" or ".<NUL>" */
+ tptr++;
+ }
+ if (tptr[1] == '/' || tptr[1] == '\0') {
+ /* skip extra "/./" */
+ goto next_char;
}
}
}
*++urlp = *tptr;
- } while (*++tptr);
- *++urlp = '\0'; /* terminate after last character */
+ if (*urlp == '\0')
+ break;
+ next_char:
+ tptr++;
+ }
/* If URL is a directory, add '/' */
if (urlp[-1] != '/') {