mirror of
https://github.com/nodejs/http-parser.git
synced 2025-10-20 05:15:13 +08:00
src: tighten header field/value loops
This commit is contained in:
@@ -128,6 +128,26 @@ 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
|
||||
* 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
|
||||
* than any reasonable request or response so this should never affect
|
||||
* day-to-day operation.
|
||||
*/
|
||||
#define COUNT_HEADER_SIZE(V) \
|
||||
do { \
|
||||
parser->nread += (V); \
|
||||
if (parser->nread > (HTTP_MAX_HEADER_SIZE)) { \
|
||||
SET_ERRNO(HPE_HEADER_OVERFLOW); \
|
||||
goto error; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define PROXY_CONNECTION "proxy-connection"
|
||||
#define CONNECTION "connection"
|
||||
@@ -655,24 +675,8 @@ size_t http_parser_execute (http_parser *parser,
|
||||
for (p=data; p != data + len; p++) {
|
||||
ch = *p;
|
||||
|
||||
if (PARSING_HEADER(CURRENT_STATE())) {
|
||||
++parser->nread;
|
||||
/* 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
|
||||
* 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
|
||||
* than any reasonable request or response so this should never affect
|
||||
* day-to-day operation.
|
||||
*/
|
||||
if (parser->nread > (HTTP_MAX_HEADER_SIZE)) {
|
||||
SET_ERRNO(HPE_HEADER_OVERFLOW);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (PARSING_HEADER(CURRENT_STATE()))
|
||||
COUNT_HEADER_SIZE(1);
|
||||
|
||||
reexecute_byte:
|
||||
switch (CURRENT_STATE()) {
|
||||
@@ -1293,9 +1297,14 @@ size_t http_parser_execute (http_parser *parser,
|
||||
|
||||
case s_header_field:
|
||||
{
|
||||
const char* start = p;
|
||||
for (; p != data + len; p++) {
|
||||
ch = *p;
|
||||
c = TOKEN(ch);
|
||||
|
||||
if (c) {
|
||||
if (!c)
|
||||
break;
|
||||
|
||||
switch (parser->header_state) {
|
||||
case h_general:
|
||||
break;
|
||||
@@ -1396,6 +1405,12 @@ size_t http_parser_execute (http_parser *parser,
|
||||
assert(0 && "Unknown header_state");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
COUNT_HEADER_SIZE(p - start);
|
||||
|
||||
if (p == data + len) {
|
||||
--p;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1478,7 +1493,9 @@ size_t http_parser_execute (http_parser *parser,
|
||||
|
||||
case s_header_value:
|
||||
{
|
||||
|
||||
const char* start = p;
|
||||
for (; p != data + len; p++) {
|
||||
ch = *p;
|
||||
if (ch == CR) {
|
||||
UPDATE_STATE(s_header_almost_done);
|
||||
CALLBACK_DATA(header_value);
|
||||
@@ -1487,6 +1504,7 @@ size_t http_parser_execute (http_parser *parser,
|
||||
|
||||
if (ch == LF) {
|
||||
UPDATE_STATE(s_header_almost_done);
|
||||
COUNT_HEADER_SIZE(p - start);
|
||||
CALLBACK_DATA_NOADVANCE(header_value);
|
||||
goto reexecute_byte;
|
||||
}
|
||||
@@ -1570,6 +1588,12 @@ size_t http_parser_execute (http_parser *parser,
|
||||
parser->header_state = h_general;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
COUNT_HEADER_SIZE(p - start);
|
||||
|
||||
if (p == data + len)
|
||||
--p;
|
||||
break;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user