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.
This commit is contained in:
Valentin Bartenev
2019-09-30 19:11:17 +03:00
parent 2791c00cf2
commit 2dbda125db

View File

@@ -970,9 +970,11 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp)
state = sw_quoted; state = sw_quoted;
continue; continue;
case '?': case '?':
u--;
args = p; args = p;
goto args; goto args;
case '#': case '#':
u--;
goto done; goto done;
default: default:
state = sw_normal; state = sw_normal;
@@ -991,30 +993,42 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp)
} }
switch (ch) { switch (ch) {
case '/': case '/':
state = sw_slash; case '?':
case '#':
u -= 5; u -= 5;
for ( ;; ) { for ( ;; ) {
if (u < rp->path.start) { if (u < rp->path.start) {
return NXT_HTTP_PARSE_INVALID; return NXT_HTTP_PARSE_INVALID;
} }
if (*u == '/') { if (*u == '/') {
u++; u++;
break; break;
} }
u--; u--;
} }
if (ch == '?') {
args = p;
goto args;
}
if (ch == '#') {
goto done;
}
state = sw_slash;
break; break;
case '%': case '%':
saved_state = state; saved_state = state;
state = sw_quoted; state = sw_quoted;
continue; continue;
case '?':
args = p;
goto args;
case '#':
goto done;
default: default:
state = sw_normal; state = sw_normal;
*u++ = ch; *u++ = ch;
@@ -1097,8 +1111,14 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp)
} }
} }
if (state >= sw_quoted) { if (state >= sw_dot) {
return NXT_HTTP_PARSE_INVALID; if (state >= sw_quoted) {
return NXT_HTTP_PARSE_INVALID;
}
/* "/." and "/.." must be normalized similar to "/./" and "/../". */
ch = '/';
goto again;
} }
args: args: