diff options
author | Valentin Bartenev <vbart@nginx.com> | 2018-01-15 20:49:59 +0300 |
---|---|---|
committer | Valentin Bartenev <vbart@nginx.com> | 2018-01-15 20:49:59 +0300 |
commit | 3fb140d6d2f8bf0344e7c311923178db808cb437 (patch) | |
tree | 139b1cf0d91895682beb6818136ab2ee6e4831ea | |
parent | 819b43fc2da414c9132c6061eabf063ae08c36dc (diff) | |
download | unit-3fb140d6d2f8bf0344e7c311923178db808cb437.tar.gz unit-3fb140d6d2f8bf0344e7c311923178db808cb437.tar.bz2 |
HTTP parser: improved error reporting.
-rw-r--r-- | src/nxt_h1proto.c | 27 | ||||
-rw-r--r-- | src/nxt_http_parse.c | 36 | ||||
-rw-r--r-- | src/nxt_http_parse.h | 6 | ||||
-rw-r--r-- | src/test/nxt_http_parse_test.c | 22 |
4 files changed, 59 insertions, 32 deletions
diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index c3a100a4..5623c019 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -190,6 +190,7 @@ nxt_h1p_header_parse(nxt_task_t *task, void *obj, void *data) nxt_buf_t *in, *b; nxt_conn_t *c; nxt_h1proto_t *h1p; + nxt_http_status_t status; nxt_http_request_t *r; nxt_socket_conf_joint_t *joint; @@ -264,7 +265,13 @@ nxt_h1p_header_parse(nxt_task_t *task, void *obj, void *data) return; } - } else if (ret == NXT_AGAIN) { + /* ret == NXT_ERROR */ + + nxt_http_request_error(task, r, NXT_HTTP_BAD_REQUEST); + return; + } + + if (ret == NXT_AGAIN) { in = c->read; if (nxt_buf_mem_free_size(&in->mem) == 0) { @@ -298,9 +305,23 @@ nxt_h1p_header_parse(nxt_task_t *task, void *obj, void *data) return; } - /* ret == NXT_ERROR */ + switch (ret) { - nxt_http_request_error(task, r, NXT_HTTP_BAD_REQUEST); + case NXT_HTTP_PARSE_INVALID: + status = NXT_HTTP_BAD_REQUEST; + break; + + case NXT_HTTP_PARSE_TOO_LARGE_FIELD: + status = NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE; + break; + + default: + case NXT_ERROR: + status = NXT_HTTP_INTERNAL_SERVER_ERROR; + break; + } + + nxt_http_request_error(task, r, status); return; fail: diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c index 65eed934..0a63ab1a 100644 --- a/src/nxt_http_parse.c +++ b/src/nxt_http_parse.c @@ -231,7 +231,7 @@ nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos, continue; } - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; } p++; @@ -306,7 +306,7 @@ nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos, return NXT_AGAIN; case NXT_HTTP_TARGET_BAD: - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; } nxt_unreachable(); @@ -332,7 +332,7 @@ rest_of_target: return NXT_AGAIN; case NXT_HTTP_TARGET_BAD: - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; default: continue; @@ -407,7 +407,7 @@ space_after_target: } if (nxt_slow_path(*p != '\n')) { - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; } *pos = p + 1; @@ -492,7 +492,7 @@ nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, u_char **pos, /* TODO */ - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; } @@ -555,7 +555,7 @@ nxt_http_parse_field_name(nxt_http_request_parse_t *rp, u_char **pos, len = p - *pos; if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_NAME)) { - return NXT_ERROR; + return NXT_HTTP_PARSE_TOO_LARGE_FIELD; } rp->field_hash = hash; @@ -569,13 +569,13 @@ name_end: if (nxt_fast_path(*p == ':')) { if (nxt_slow_path(p == *pos)) { - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; } len = p - *pos; if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_NAME)) { - return NXT_ERROR; + return NXT_HTTP_PARSE_TOO_LARGE_FIELD; } rp->field_hash = hash; @@ -589,7 +589,7 @@ name_end: } if (nxt_slow_path(p != *pos)) { - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; } return nxt_http_parse_field_end(rp, pos, end); @@ -630,7 +630,7 @@ nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos, len = p - *pos; if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_VALUE)) { - return NXT_ERROR; + return NXT_HTTP_PARSE_TOO_LARGE_FIELD; } rp->field_value.length = len; @@ -645,7 +645,7 @@ nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos, } if (ch == '\0') { - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; } } @@ -658,7 +658,7 @@ nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos, len = p - *pos; if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_VALUE)) { - return NXT_ERROR; + return NXT_HTTP_PARSE_TOO_LARGE_FIELD; } rp->field_value.length = len; @@ -784,7 +784,7 @@ nxt_http_parse_field_end(nxt_http_request_parse_t *rp, u_char **pos, return NXT_DONE; } - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; } @@ -976,7 +976,7 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) u -= 5; for ( ;; ) { if (u < rp->path.start) { - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; } if (*u == '/') { u++; @@ -1022,7 +1022,7 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) continue; } - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; case sw_quoted_second: if (ch >= '0' && ch <= '9') { @@ -1034,7 +1034,7 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) continue; } else if (ch == '\0') { - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; } state = saved_state; @@ -1058,12 +1058,12 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) goto again; } - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; } } if (state >= sw_quoted) { - return NXT_ERROR; + return NXT_HTTP_PARSE_INVALID; } args: diff --git a/src/nxt_http_parse.h b/src/nxt_http_parse.h index 293c4d0e..0a0ca340 100644 --- a/src/nxt_http_parse.h +++ b/src/nxt_http_parse.h @@ -8,6 +8,12 @@ #define _NXT_HTTP_PARSER_H_INCLUDED_ +typedef enum { + NXT_HTTP_PARSE_INVALID = 1, + NXT_HTTP_PARSE_TOO_LARGE_FIELD, +} nxt_http_parse_error_t; + + typedef struct nxt_http_request_parse_s nxt_http_request_parse_t; typedef struct nxt_http_field_s nxt_http_field_t; typedef struct nxt_http_fields_hash_s nxt_http_fields_hash_t; diff --git a/src/test/nxt_http_parse_test.c b/src/test/nxt_http_parse_test.c index bd577e10..637e9298 100644 --- a/src/test/nxt_http_parse_test.c +++ b/src/test/nxt_http_parse_test.c @@ -101,27 +101,27 @@ static nxt_http_parse_test_case_t nxt_http_test_cases[] = { }, { nxt_string("GEt / HTTP/1.0\r\n\r\n"), - NXT_ERROR, + NXT_HTTP_PARSE_INVALID, NULL, { NULL } }, { nxt_string("GET /\0 HTTP/1.0\r\n\r\n"), - NXT_ERROR, + NXT_HTTP_PARSE_INVALID, NULL, { NULL } }, { nxt_string("GET /\r HTTP/1.0\r\n\r\n"), - NXT_ERROR, + NXT_HTTP_PARSE_INVALID, NULL, { NULL } }, { nxt_string("GET /\n HTTP/1.0\r\n\r\n"), - NXT_ERROR, + NXT_HTTP_PARSE_INVALID, NULL, { NULL } }, { nxt_string("GET / HTTP/1.0\r\r\n"), - NXT_ERROR, + NXT_HTTP_PARSE_INVALID, NULL, { NULL } }, { @@ -230,13 +230,13 @@ static nxt_http_parse_test_case_t nxt_http_test_cases[] = { { nxt_string("GET / HTTP/1.1\r\n" "Host example.com\r\n\r\n"), - NXT_ERROR, + NXT_HTTP_PARSE_INVALID, NULL, { NULL } }, { nxt_string("GET / HTTP/1.1\r\n" ":Host: example.com\r\n\r\n"), - NXT_ERROR, + NXT_HTTP_PARSE_INVALID, NULL, { NULL } }, { @@ -248,25 +248,25 @@ static nxt_http_parse_test_case_t nxt_http_test_cases[] = { { nxt_string("GET / HTTP/1.1\r\n" "Ho\0st: example.com\r\n\r\n"), - NXT_ERROR, + NXT_HTTP_PARSE_INVALID, NULL, { NULL } }, { nxt_string("GET / HTTP/1.1\r\n" "Ho\rst: example.com\r\n\r\n"), - NXT_ERROR, + NXT_HTTP_PARSE_INVALID, NULL, { NULL } }, { nxt_string("GET / HTTP/1.1\r\n" "Host: exa\0mple.com\r\n\r\n"), - NXT_ERROR, + NXT_HTTP_PARSE_INVALID, NULL, { NULL } }, { nxt_string("GET / HTTP/1.1\r\n" "Host: exa\rmple.com\r\n\r\n"), - NXT_ERROR, + NXT_HTTP_PARSE_INVALID, NULL, { NULL } }, { |