X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=vendor%2Fhttp_parser%2Fhttp_parser.c;h=e2fc5d2ee7a71718839911446d3e7e0de9f293c7;hb=1ab93cf7026d690f47dcd4af068049838ae92533;hp=9941b7ea17494683169a3e86925f48b2ab150ce5;hpb=77730fd5f09f8fc193205654c8bba84d34365670;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/vendor/http_parser/http_parser.c b/vendor/http_parser/http_parser.c index 9941b7ea1..e2fc5d2ee 100644 --- a/vendor/http_parser/http_parser.c +++ b/vendor/http_parser/http_parser.c @@ -25,6 +25,8 @@ #include #include +static uint32_t max_header_size = HTTP_MAX_HEADER_SIZE; + #ifndef ULLONG_MAX # define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ #endif @@ -139,20 +141,20 @@ do { \ } while (0) /* Don't allow the total size of the HTTP headers (including the status - * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect + * line) to exceed max_header_size. This check is here to protect * embedders against denial-of-service attacks where the attacker feeds * us a never-ending header that the embedder keeps buffering. * * This check is arguably the responsibility of embedders but we're doing * it on the embedder's behalf because most won't bother and this way we - * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger + * make the web a little safer. max_header_size is still far bigger * than any reasonable request or response so this should never affect * day-to-day operation. */ #define COUNT_HEADER_SIZE(V) \ do { \ - nread += (V); \ - if (UNLIKELY(nread > (HTTP_MAX_HEADER_SIZE))) { \ + nread += (uint32_t)(V); \ + if (UNLIKELY(nread > max_header_size)) { \ SET_ERRNO(HPE_HEADER_OVERFLOW); \ goto error; \ } \ @@ -314,6 +316,8 @@ enum state , s_req_http_HT , s_req_http_HTT , s_req_http_HTTP + , s_req_http_I + , s_req_http_IC , s_req_http_major , s_req_http_dot , s_req_http_minor @@ -1084,11 +1088,17 @@ reexecute: case s_req_http_start: switch (ch) { + case ' ': + break; case 'H': UPDATE_STATE(s_req_http_H); break; - case ' ': - break; + case 'I': + if (parser->method == HTTP_SOURCE) { + UPDATE_STATE(s_req_http_I); + break; + } + /* fall through */ default: SET_ERRNO(HPE_INVALID_CONSTANT); goto error; @@ -1110,6 +1120,16 @@ reexecute: UPDATE_STATE(s_req_http_HTTP); break; + case s_req_http_I: + STRICT_CHECK(ch != 'C'); + UPDATE_STATE(s_req_http_IC); + break; + + case s_req_http_IC: + STRICT_CHECK(ch != 'E'); + UPDATE_STATE(s_req_http_HTTP); /* Treat "ICE" as "HTTP". */ + break; + case s_req_http_HTTP: STRICT_CHECK(ch != '/'); UPDATE_STATE(s_req_http_major); @@ -1238,7 +1258,7 @@ reexecute: switch (parser->header_state) { case h_general: { size_t limit = data + len - p; - limit = MIN(limit, HTTP_MAX_HEADER_SIZE); + limit = MIN(limit, max_header_size); while (p+1 < data + limit && TOKEN(p[1])) { p++; } @@ -1416,6 +1436,11 @@ reexecute: parser->header_state = h_content_length_num; break; + /* when obsolete line folding is encountered for content length + * continue to the s_header_value state */ + case h_content_length_ws: + break; + case h_connection: /* looking for 'Connection: keep-alive' */ if (c == 'k') { @@ -1476,7 +1501,7 @@ reexecute: const char* p_lf; size_t limit = data + len - p; - limit = MIN(limit, HTTP_MAX_HEADER_SIZE); + limit = MIN(limit, max_header_size); p_cr = (const char*) memchr(p, CR, limit); p_lf = (const char*) memchr(p, LF, limit); @@ -1659,6 +1684,10 @@ reexecute: case s_header_value_lws: { if (ch == ' ' || ch == '\t') { + if (parser->header_state == h_content_length_num) { + /* treat obsolete line folding as space */ + parser->header_state = h_content_length_ws; + } UPDATE_STATE(s_header_value_start); REEXECUTE(); } @@ -1711,6 +1740,11 @@ reexecute: case h_transfer_encoding_chunked: parser->flags |= F_CHUNKED; break; + case h_content_length: + /* do not allow empty content length */ + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + goto error; + break; default: break; } @@ -2247,14 +2281,14 @@ http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { switch(new_s) { case s_http_host: if (s != s_http_host) { - u->field_data[UF_HOST].off = p - buf; + u->field_data[UF_HOST].off = (uint16_t)(p - buf); } u->field_data[UF_HOST].len++; break; case s_http_host_v6: if (s != s_http_host_v6) { - u->field_data[UF_HOST].off = p - buf; + u->field_data[UF_HOST].off = (uint16_t)(p - buf); } u->field_data[UF_HOST].len++; break; @@ -2266,7 +2300,7 @@ http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { case s_http_host_port: if (s != s_http_host_port) { - u->field_data[UF_PORT].off = p - buf; + u->field_data[UF_PORT].off = (uint16_t)(p - buf); u->field_data[UF_PORT].len = 0; u->field_set |= (1 << UF_PORT); } @@ -2275,7 +2309,7 @@ http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { case s_http_userinfo: if (s != s_http_userinfo) { - u->field_data[UF_USERINFO].off = p - buf ; + u->field_data[UF_USERINFO].off = (uint16_t)(p - buf); u->field_data[UF_USERINFO].len = 0; u->field_set |= (1 << UF_USERINFO); } @@ -2379,7 +2413,7 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect, continue; } - u->field_data[uf].off = p - buf; + u->field_data[uf].off = (uint16_t)(p - buf); u->field_data[uf].len = 1; u->field_set |= (1 << uf); @@ -2460,3 +2494,8 @@ http_parser_version(void) { HTTP_PARSER_VERSION_MINOR * 0x00100 | HTTP_PARSER_VERSION_PATCH * 0x00001; } + +void +http_parser_set_max_header_size(uint32_t size) { + max_header_size = size; +}