summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-12-16 00:37:02 (GMT)
committer Denys Vlasenko <vda.linux@googlemail.com>2011-12-16 00:37:02 (GMT)
commitb05cd6b7a768039fa799f62634bdc83cb5803ed7 (patch)
tree74c58f2181aa60a78e63c9cb50db270c7d7aa4f0
parentcda6ea905d448e2a2058b5eb44db50b256659b50 (diff)
downloadbusybox-b05cd6b7a768039fa799f62634bdc83cb5803ed7.tar.gz
busybox-b05cd6b7a768039fa799f62634bdc83cb5803ed7.tar.bz2
httpd: fix /../ sanitization (had one extra semicolon). rewrote it
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-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] != '/') {