diff options
-rw-r--r-- | src/nxt_h1proto.c | 5 | ||||
-rw-r--r-- | src/nxt_http.h | 1 | ||||
-rw-r--r-- | src/nxt_http_parse.c | 36 | ||||
-rw-r--r-- | src/nxt_http_parse.h | 1 | ||||
-rw-r--r-- | src/test/nxt_http_parse_test.c | 5 |
5 files changed, 35 insertions, 13 deletions
diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index ac60753d..e5141757 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -311,6 +311,10 @@ nxt_h1p_header_parse(nxt_task_t *task, void *obj, void *data) status = NXT_HTTP_BAD_REQUEST; break; + case NXT_HTTP_PARSE_UNSUPPORTED_VERSION: + status = NXT_HTTP_VERSION_NOT_SUPPORTED; + break; + case NXT_HTTP_PARSE_TOO_LARGE_FIELD: status = NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE; break; @@ -594,6 +598,7 @@ static const nxt_str_t nxt_http_server_error[] = { nxt_string("HTTP/1.1 502 Bad Gateway\r\n"), nxt_string("HTTP/1.1 503 Service Unavailable\r\n"), nxt_string("HTTP/1.1 504 Gateway Timeout\r\n"), + nxt_string("HTTP/1.1 505 HTTP Version Not Supported\r\n"), }; diff --git a/src/nxt_http.h b/src/nxt_http.h index f3143687..a8a28eca 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -30,6 +30,7 @@ typedef enum { NXT_HTTP_BAD_GATEWAY = 502, NXT_HTTP_SERVICE_UNAVAILABLE = 503, NXT_HTTP_GATEWAY_TIMEOUT = 504, + NXT_HTTP_VERSION_NOT_SUPPORTED = 505, } nxt_http_status_t; diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c index ef9fee45..975fdd98 100644 --- a/src/nxt_http_parse.c +++ b/src/nxt_http_parse.c @@ -383,15 +383,24 @@ space_after_target: /* " HTTP/1.1\r\n" or " HTTP/1.1\n" */ + if (nxt_slow_path(p[9] != '\r' && p[9] != '\n')) { + + if (p[1] == ' ') { + /* surplus space after tartet */ + p++; + goto space_after_target; + } + + rp->space_in_target = 1; + goto rest_of_target; + } + nxt_memcpy(ver.str, &p[1], 8); - if (nxt_fast_path((ver.ui64 == http11.ui64 - || ver.ui64 == http10.ui64 - || (nxt_memcmp(ver.s.prefix, "HTTP/", 5) == 0 - && ver.s.major >= '0' && ver.s.major <= '9' - && ver.s.point == '.' - && ver.s.minor >= '0' && ver.s.minor <= '9')) - && (p[9] == '\r' || p[9] == '\n'))) + if (nxt_fast_path(ver.ui64 == http11.ui64 + || ver.ui64 == http10.ui64 + || (nxt_memcmp(ver.str, "HTTP/1.", 7) == 0 + && ver.s.minor >= '0' && ver.s.minor <= '9'))) { rp->version.ui64 = ver.ui64; @@ -443,14 +452,15 @@ space_after_target: return nxt_http_parse_field_name(rp, pos, end); } - if (p[1] == ' ') { - /* surplus space after tartet */ - p++; - goto space_after_target; + if (nxt_memcmp(ver.s.prefix, "HTTP/", 5) == 0 + && ver.s.major >= '0' && ver.s.major <= '9' + && ver.s.point == '.' + && ver.s.minor >= '0' && ver.s.minor <= '9') + { + return NXT_HTTP_PARSE_UNSUPPORTED_VERSION; } - rp->space_in_target = 1; - goto rest_of_target; + return NXT_HTTP_PARSE_INVALID; } diff --git a/src/nxt_http_parse.h b/src/nxt_http_parse.h index 51c6809a..0326d45c 100644 --- a/src/nxt_http_parse.h +++ b/src/nxt_http_parse.h @@ -10,6 +10,7 @@ typedef enum { NXT_HTTP_PARSE_INVALID = 1, + NXT_HTTP_PARSE_UNSUPPORTED_VERSION, NXT_HTTP_PARSE_TOO_LARGE_FIELD, } nxt_http_parse_error_t; diff --git a/src/test/nxt_http_parse_test.c b/src/test/nxt_http_parse_test.c index 637e9298..3da10766 100644 --- a/src/test/nxt_http_parse_test.c +++ b/src/test/nxt_http_parse_test.c @@ -125,6 +125,11 @@ static nxt_http_parse_test_case_t nxt_http_test_cases[] = { NULL, { NULL } }, { + nxt_string("GET / HTTP/2.0\r\n"), + NXT_HTTP_PARSE_UNSUPPORTED_VERSION, + NULL, { NULL } + }, + { nxt_string("GET /. HTTP/1.0\r\n\r\n"), NXT_DONE, &nxt_http_parse_test_request_line, |