diff options
author | Denys Vlasenko | 2011-12-16 01:37:02 +0100 |
---|---|---|
committer | Denys Vlasenko | 2011-12-16 01:37:02 +0100 |
commit | b05cd6b7a768039fa799f62634bdc83cb5803ed7 (patch) | |
tree | 74c58f2181aa60a78e63c9cb50db270c7d7aa4f0 | |
parent | cda6ea905d448e2a2058b5eb44db50b256659b50 (diff) | |
download | busybox-b05cd6b7a768039fa799f62634bdc83cb5803ed7.zip busybox-b05cd6b7a768039fa799f62634bdc83cb5803ed7.tar.gz |
httpd: fix /../ sanitization (had one extra semicolon). rewrote it
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/httpd.c | 32 |
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] != '/') { |