mirror of
https://github.com/xmrig/xmrig.git
synced 2025-12-07 16:05:05 -05:00
http-parser updated to latest version.
This commit is contained in:
128
src/3rdparty/http-parser/http_parser.c
vendored
128
src/3rdparty/http-parser/http_parser.c
vendored
@@ -381,7 +381,10 @@ enum header_states
|
||||
, h_transfer_encoding
|
||||
, h_upgrade
|
||||
|
||||
, h_matching_transfer_encoding_token_start
|
||||
, h_matching_transfer_encoding_chunked
|
||||
, h_matching_transfer_encoding_token
|
||||
|
||||
, h_matching_connection_token_start
|
||||
, h_matching_connection_keep_alive
|
||||
, h_matching_connection_close
|
||||
@@ -1257,9 +1260,9 @@ reexecute:
|
||||
|
||||
switch (parser->header_state) {
|
||||
case h_general: {
|
||||
size_t limit = data + len - p;
|
||||
limit = MIN(limit, max_header_size);
|
||||
while (p+1 < data + limit && TOKEN(p[1])) {
|
||||
size_t left = data + len - p;
|
||||
const char* pe = p + MIN(left, max_header_size);
|
||||
while (p+1 < pe && TOKEN(p[1])) {
|
||||
p++;
|
||||
}
|
||||
break;
|
||||
@@ -1335,6 +1338,7 @@ reexecute:
|
||||
parser->header_state = h_general;
|
||||
} else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
|
||||
parser->header_state = h_transfer_encoding;
|
||||
parser->flags |= F_TRANSFER_ENCODING;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1416,10 +1420,14 @@ reexecute:
|
||||
if ('c' == c) {
|
||||
parser->header_state = h_matching_transfer_encoding_chunked;
|
||||
} else {
|
||||
parser->header_state = h_general;
|
||||
parser->header_state = h_matching_transfer_encoding_token;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Multi-value `Transfer-Encoding` header */
|
||||
case h_matching_transfer_encoding_token_start:
|
||||
break;
|
||||
|
||||
case h_content_length:
|
||||
if (UNLIKELY(!IS_NUM(ch))) {
|
||||
SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
|
||||
@@ -1496,28 +1504,25 @@ reexecute:
|
||||
|
||||
switch (h_state) {
|
||||
case h_general:
|
||||
{
|
||||
const char* p_cr;
|
||||
const char* p_lf;
|
||||
size_t limit = data + len - p;
|
||||
{
|
||||
size_t left = data + len - p;
|
||||
const char* pe = p + MIN(left, 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);
|
||||
if (p_cr != NULL) {
|
||||
if (p_lf != NULL && p_cr >= p_lf)
|
||||
p = p_lf;
|
||||
else
|
||||
p = p_cr;
|
||||
} else if (UNLIKELY(p_lf != NULL)) {
|
||||
p = p_lf;
|
||||
} else {
|
||||
p = data + len;
|
||||
for (; p != pe; p++) {
|
||||
ch = *p;
|
||||
if (ch == CR || ch == LF) {
|
||||
--p;
|
||||
break;
|
||||
}
|
||||
if (!lenient && !IS_HEADER_CHAR(ch)) {
|
||||
SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (p == data + len)
|
||||
--p;
|
||||
break;
|
||||
}
|
||||
--p;
|
||||
break;
|
||||
}
|
||||
|
||||
case h_connection:
|
||||
case h_transfer_encoding:
|
||||
@@ -1566,16 +1571,41 @@ reexecute:
|
||||
goto error;
|
||||
|
||||
/* Transfer-Encoding: chunked */
|
||||
case h_matching_transfer_encoding_token_start:
|
||||
/* looking for 'Transfer-Encoding: chunked' */
|
||||
if ('c' == c) {
|
||||
h_state = h_matching_transfer_encoding_chunked;
|
||||
} else if (STRICT_TOKEN(c)) {
|
||||
/* TODO(indutny): similar code below does this, but why?
|
||||
* At the very least it seems to be inconsistent given that
|
||||
* h_matching_transfer_encoding_token does not check for
|
||||
* `STRICT_TOKEN`
|
||||
*/
|
||||
h_state = h_matching_transfer_encoding_token;
|
||||
} else if (c == ' ' || c == '\t') {
|
||||
/* Skip lws */
|
||||
} else {
|
||||
h_state = h_general;
|
||||
}
|
||||
break;
|
||||
|
||||
case h_matching_transfer_encoding_chunked:
|
||||
parser->index++;
|
||||
if (parser->index > sizeof(CHUNKED)-1
|
||||
|| c != CHUNKED[parser->index]) {
|
||||
h_state = h_general;
|
||||
h_state = h_matching_transfer_encoding_token;
|
||||
} else if (parser->index == sizeof(CHUNKED)-2) {
|
||||
h_state = h_transfer_encoding_chunked;
|
||||
}
|
||||
break;
|
||||
|
||||
case h_matching_transfer_encoding_token:
|
||||
if (ch == ',') {
|
||||
h_state = h_matching_transfer_encoding_token_start;
|
||||
parser->index = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case h_matching_connection_token_start:
|
||||
/* looking for 'Connection: keep-alive' */
|
||||
if (c == 'k') {
|
||||
@@ -1634,7 +1664,7 @@ reexecute:
|
||||
break;
|
||||
|
||||
case h_transfer_encoding_chunked:
|
||||
if (ch != ' ') h_state = h_general;
|
||||
if (ch != ' ') h_state = h_matching_transfer_encoding_token;
|
||||
break;
|
||||
|
||||
case h_connection_keep_alive:
|
||||
@@ -1768,12 +1798,17 @@ reexecute:
|
||||
REEXECUTE();
|
||||
}
|
||||
|
||||
/* Cannot use chunked encoding and a content-length header together
|
||||
per the HTTP specification. */
|
||||
if ((parser->flags & F_CHUNKED) &&
|
||||
/* Cannot us transfer-encoding and a content-length header together
|
||||
per the HTTP specification. (RFC 7230 Section 3.3.3) */
|
||||
if ((parser->flags & F_TRANSFER_ENCODING) &&
|
||||
(parser->flags & F_CONTENTLENGTH)) {
|
||||
SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
|
||||
goto error;
|
||||
/* Allow it for lenient parsing as long as `Transfer-Encoding` is
|
||||
* not `chunked`
|
||||
*/
|
||||
if (!lenient || (parser->flags & F_CHUNKED)) {
|
||||
SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
UPDATE_STATE(s_headers_done);
|
||||
@@ -1848,8 +1883,31 @@ reexecute:
|
||||
UPDATE_STATE(NEW_MESSAGE());
|
||||
CALLBACK_NOTIFY(message_complete);
|
||||
} else if (parser->flags & F_CHUNKED) {
|
||||
/* chunked encoding - ignore Content-Length header */
|
||||
/* chunked encoding - ignore Content-Length header,
|
||||
* prepare for a chunk */
|
||||
UPDATE_STATE(s_chunk_size_start);
|
||||
} else if (parser->flags & F_TRANSFER_ENCODING) {
|
||||
if (parser->type == HTTP_REQUEST && !lenient) {
|
||||
/* RFC 7230 3.3.3 */
|
||||
|
||||
/* If a Transfer-Encoding header field
|
||||
* is present in a request and the chunked transfer coding is not
|
||||
* the final encoding, the message body length cannot be determined
|
||||
* reliably; the server MUST respond with the 400 (Bad Request)
|
||||
* status code and then close the connection.
|
||||
*/
|
||||
SET_ERRNO(HPE_INVALID_TRANSFER_ENCODING);
|
||||
RETURN(p - data); /* Error */
|
||||
} else {
|
||||
/* RFC 7230 3.3.3 */
|
||||
|
||||
/* If a Transfer-Encoding header field is present in a response and
|
||||
* the chunked transfer coding is not the final encoding, the
|
||||
* message body length is determined by reading the connection until
|
||||
* it is closed by the server.
|
||||
*/
|
||||
UPDATE_STATE(s_body_identity_eof);
|
||||
}
|
||||
} else {
|
||||
if (parser->content_length == 0) {
|
||||
/* Content-Length header given but zero: Content-Length: 0\r\n */
|
||||
@@ -2103,6 +2161,12 @@ http_message_needs_eof (const http_parser *parser)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RFC 7230 3.3.3, see `s_headers_almost_done` */
|
||||
if ((parser->flags & F_TRANSFER_ENCODING) &&
|
||||
(parser->flags & F_CHUNKED) == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user