From cdcb1b77379f780b7b187d711c44181dbd0a6e24 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Thu, 29 Nov 2018 17:29:53 -0500 Subject: [PATCH 1/3] deps: cherry-pick http_parser_set_max_header_size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds http_parser_set_max_header_size() to the http-parser for overriding the compile time maximum HTTP header size. PR-URL: https://github.com/nodejs/node/pull/24811 Fixes: https://github.com/nodejs/node/issues/24692 Refs: https://github.com/nodejs/http-parser/pull/453 Reviewed-By: Anna Henningsen Reviewed-By: Matteo Collina Reviewed-By: Myles Borins Reviewed-By: Michael Dawson Reviewed-By: Сковорода Никита Андреевич Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel --- deps/http_parser/http_parser.c | 15 +++++++++++---- deps/http_parser/http_parser.h | 3 +++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/deps/http_parser/http_parser.c b/deps/http_parser/http_parser.c index 6522618671d09c..46764bced09478 100644 --- a/deps/http_parser/http_parser.c +++ b/deps/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 @@ -137,20 +139,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 { \ parser->nread += (V); \ - if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \ + if (UNLIKELY(parser->nread > max_header_size)) { \ SET_ERRNO(HPE_HEADER_OVERFLOW); \ goto error; \ } \ @@ -1471,7 +1473,7 @@ size_t http_parser_execute (http_parser *parser, 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); @@ -2437,3 +2439,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; +} diff --git a/deps/http_parser/http_parser.h b/deps/http_parser/http_parser.h index 1fbf30e2b4740b..ea7bafef2c3178 100644 --- a/deps/http_parser/http_parser.h +++ b/deps/http_parser/http_parser.h @@ -427,6 +427,9 @@ void http_parser_pause(http_parser *parser, int paused); /* Checks if this is the final chunk of the body. */ int http_body_is_final(const http_parser *parser); +/* Change the maximum header size provided at compile time. */ +void http_parser_set_max_header_size(uint32_t size); + #ifdef __cplusplus } #endif From 436f4de38f511508710eb1492f4d23a9f427e7f7 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Tue, 18 Dec 2018 12:12:21 +0100 Subject: [PATCH 2/3] src: add kUInteger parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds support for uint64_t option parsing. PR-URL: https://github.com/nodejs/node/pull/24811 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: Myles Borins Reviewed-By: Michael Dawson Reviewed-By: Сковорода Никита Андреевич Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel --- lib/internal/print_help.js | 1 + src/node_options-inl.h | 16 ++++++++++++++++ src/node_options.cc | 4 ++++ src/node_options.h | 5 +++++ 4 files changed, 26 insertions(+) diff --git a/lib/internal/print_help.js b/lib/internal/print_help.js index c3e984dd9f4987..fdec7bd09bd87e 100644 --- a/lib/internal/print_help.js +++ b/lib/internal/print_help.js @@ -69,6 +69,7 @@ function getArgDescription(type) { case 'kHostPort': return '[host:]port'; case 'kInteger': + case 'kUInteger': case 'kString': case 'kStringList': return '...'; diff --git a/src/node_options-inl.h b/src/node_options-inl.h index d25557e6a50637..f482bcd36660ed 100644 --- a/src/node_options-inl.h +++ b/src/node_options-inl.h @@ -39,6 +39,19 @@ void OptionsParser::AddOption(const std::string& name, help_text}); } +template +void OptionsParser::AddOption(const std::string& name, + const std::string& help_text, + uint64_t Options::* field, + OptionEnvvarSettings env_setting) { + options_.emplace( + name, + OptionInfo{kUInteger, + std::make_shared>(field), + env_setting, + help_text}); +} + template void OptionsParser::AddOption(const std::string& name, const std::string& help_text, @@ -401,6 +414,9 @@ void OptionsParser::Parse( case kInteger: *Lookup(info.field, options) = std::atoll(value.c_str()); break; + case kUInteger: + *Lookup(info.field, options) = std::stoull(value.c_str()); + break; case kString: *Lookup(info.field, options) = value; break; diff --git a/src/node_options.cc b/src/node_options.cc index d665bc40400071..d4cc19eb021a38 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -429,6 +429,9 @@ void GetOptions(const FunctionCallbackInfo& args) { case kInteger: value = Number::New(isolate, *parser.Lookup(field, opts)); break; + case kUInteger: + value = Number::New(isolate, *parser.Lookup(field, opts)); + break; case kString: if (!ToV8Value(context, *parser.Lookup(field, opts)) .ToLocal(&value)) { @@ -516,6 +519,7 @@ void Initialize(Local target, NODE_DEFINE_CONSTANT(types, kV8Option); NODE_DEFINE_CONSTANT(types, kBoolean); NODE_DEFINE_CONSTANT(types, kInteger); + NODE_DEFINE_CONSTANT(types, kUInteger); NODE_DEFINE_CONSTANT(types, kString); NODE_DEFINE_CONSTANT(types, kHostPort); NODE_DEFINE_CONSTANT(types, kStringList); diff --git a/src/node_options.h b/src/node_options.h index d317e12b6f0db8..f5489900b45fd0 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -203,6 +203,7 @@ enum OptionType { kV8Option, kBoolean, kInteger, + kUInteger, kString, kHostPort, kStringList, @@ -229,6 +230,10 @@ class OptionsParser { const std::string& help_text, bool Options::* field, OptionEnvvarSettings env_setting = kDisallowedInEnvironment); + void AddOption(const std::string& name, + const std::string& help_text, + uint64_t Options::* field, + OptionEnvvarSettings env_setting = kDisallowedInEnvironment); void AddOption(const std::string& name, const std::string& help_text, int64_t Options::* field, From 632f2633249dc0f295e9d2abab33baaf0f75ce6f Mon Sep 17 00:00:00 2001 From: cjihrig Date: Mon, 3 Dec 2018 12:27:46 -0500 Subject: [PATCH 3/3] cli: add --max-http-header-size flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow the maximum size of HTTP headers to be overridden from the command line. co-authored-by: Matteo Collina PR-URL: https://github.com/nodejs/node/pull/24811 Fixes: https://github.com/nodejs/node/issues/24692 Reviewed-By: Anna Henningsen Reviewed-By: Myles Borins Reviewed-By: Michael Dawson Reviewed-By: Сковорода Никита Андреевич Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel --- doc/api/cli.md | 8 ++ doc/node.1 | 3 + src/node_http_parser_impl.h | 18 ++- src/node_options.cc | 4 + src/node_options.h | 1 + test/sequential/test-http-max-http-headers.js | 69 +++++++---- .../test-set-http-max-http-headers.js | 109 ++++++++++++++++++ 7 files changed, 184 insertions(+), 28 deletions(-) create mode 100644 test/sequential/test-set-http-max-http-headers.js diff --git a/doc/api/cli.md b/doc/api/cli.md index 22e087f31725e2..97cfea239e4f1f 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -197,6 +197,13 @@ added: v9.0.0 Specify the `file` of the custom [experimental ECMAScript Module][] loader. +### `--max-http-header-size=size` + + +Specify the maximum size, in bytes, of HTTP headers. Defaults to 8KB. + ### `--napi-modules`