diff options
author | Valentin Bartenev <vbart@nginx.com> | 2019-09-30 19:11:17 +0300 |
---|---|---|
committer | Valentin Bartenev <vbart@nginx.com> | 2019-09-30 19:11:17 +0300 |
commit | 2dbda125db743f71d4dd104b29fa58620eb49de2 (patch) | |
tree | 751939d39c22fa5e801993e9ca820a3cde5ed7a5 /src/nxt_http_parse.c | |
parent | 2791c00cf2df1b4c86179756f7c56064219f482f (diff) | |
download | unit-2dbda125db743f71d4dd104b29fa58620eb49de2.tar.gz unit-2dbda125db743f71d4dd104b29fa58620eb49de2.tar.bz2 |
HTTP parser: normalization of paths ending with "." or "..".
Earlier, the paths were normalized only if there was a "/" at the end, which
is wrong according to section 5.2.4 of RFC 3986 and hypothetically may allow
to the directory above the document root.
Diffstat (limited to 'src/nxt_http_parse.c')
-rw-r--r-- | src/nxt_http_parse.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c index 5b009d96..63fd5130 100644 --- a/src/nxt_http_parse.c +++ b/src/nxt_http_parse.c @@ -970,9 +970,11 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) state = sw_quoted; continue; case '?': + u--; args = p; goto args; case '#': + u--; goto done; default: state = sw_normal; @@ -991,30 +993,42 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) } switch (ch) { + case '/': - state = sw_slash; + case '?': + case '#': u -= 5; + for ( ;; ) { if (u < rp->path.start) { return NXT_HTTP_PARSE_INVALID; } + if (*u == '/') { u++; break; } + u--; } + + if (ch == '?') { + args = p; + goto args; + } + + if (ch == '#') { + goto done; + } + + state = sw_slash; break; case '%': saved_state = state; state = sw_quoted; continue; - case '?': - args = p; - goto args; - case '#': - goto done; + default: state = sw_normal; *u++ = ch; @@ -1097,8 +1111,14 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) } } - if (state >= sw_quoted) { - return NXT_HTTP_PARSE_INVALID; + if (state >= sw_dot) { + if (state >= sw_quoted) { + return NXT_HTTP_PARSE_INVALID; + } + + /* "/." and "/.." must be normalized similar to "/./" and "/../". */ + ch = '/'; + goto again; } args: |