diff --git a/Disable-running-gyp-on-shared-deps.patch b/0001-Disable-running-gyp-on-shared-deps.patch similarity index 62% rename from Disable-running-gyp-on-shared-deps.patch rename to 0001-Disable-running-gyp-on-shared-deps.patch index 7db5731e019b8bd6614aaa7a177b01e2c896167d..3c11dd8747bbd2cdb47fdc77dcac8480ef08aed2 100644 --- a/Disable-running-gyp-on-shared-deps.patch +++ b/0001-Disable-running-gyp-on-shared-deps.patch @@ -1,10 +1,17 @@ +From 7a6257be1d0276ff22d2d92ea89c5bca6c633802 Mon Sep 17 00:00:00 2001 +From: Zuzana Svetlikova +Date: Thu, 27 Apr 2017 14:25:42 +0200 +Subject: [PATCH 1/3] Disable running gyp on shared deps + +--- + Makefile | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + diff --git a/Makefile b/Makefile -index 5fc2bb0c58f5532044a14e9f9595b2316f562726..f1c1545caa220d7442d6d92c49412ec7554de123 100644 +index 316410e3f81e39cdddecf91d5b717c884a9c51b3..62c8ebb5b95a68e44d4c2ab3beee70d63c3175c7 100644 --- a/Makefile +++ b/Makefile -@@ -121,14 +121,13 @@ with-code-cache: - - .PHONY: test-code-cache +@@ -123,10 +123,9 @@ with-code-cache: test-code-cache: with-code-cache $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) code-cache @@ -18,8 +25,6 @@ index 5fc2bb0c58f5532044a14e9f9595b2316f562726..f1c1545caa220d7442d6d92c49412ec7 $(PYTHON) tools/gyp_node.py -f make config.gypi: configure configure.py - @if [ -x config.status ]; then \ - ./config.status; \ -- -2.19.0 +2.24.1 diff --git a/0002-Install-both-binaries-and-use-libdir.patch b/0002-Install-both-binaries-and-use-libdir.patch new file mode 100644 index 0000000000000000000000000000000000000000..9e184d7e926bdc2c6914a91365a6620725ac0955 --- /dev/null +++ b/0002-Install-both-binaries-and-use-libdir.patch @@ -0,0 +1,86 @@ +From 8828c8fdc98f310a718a65ebc47d8a163e41b0cb Mon Sep 17 00:00:00 2001 +From: Elliott Sales de Andrade +Date: Tue, 19 Mar 2019 23:22:40 -0400 +Subject: [PATCH 2/3] Install both binaries and use libdir. + +This allows us to build with a shared library for other users while +still providing the normal executable. + +Signed-off-by: Elliott Sales de Andrade +--- + configure.py | 7 +++++++ + tools/install.py | 29 +++++++++++++---------------- + 2 files changed, 20 insertions(+), 16 deletions(-) + +diff --git a/configure.py b/configure.py +index 22861a10eeac54cae69fc1be4b9aef7ed5106a35..48389fbdcb57cbf8d9c11d4921c65f34a1937cc7 100755 +--- a/configure.py ++++ b/configure.py +@@ -552,6 +552,12 @@ parser.add_option('--shared', + help='compile shared library for embedding node in another project. ' + + '(This mode is not officially supported for regular applications)') + ++parser.add_option('--libdir', ++ action='store', ++ dest='libdir', ++ default='lib', ++ help='a directory to install the shared library into') ++ + parser.add_option('--without-v8-platform', + action='store_true', + dest='without_v8_platform', +@@ -1095,6 +1101,7 @@ def configure_node(o): + if options.code_cache_path: + o['variables']['node_code_cache_path'] = options.code_cache_path + o['variables']['node_shared'] = b(options.shared) ++ o['variables']['libdir'] = options.libdir + node_module_version = getmoduleversion.get_version() + + if sys.platform == 'darwin': +diff --git a/tools/install.py b/tools/install.py +index 028c32ecbbdf9625238dfcc2baef66df9408b539..bf443c4d15a3b3ebf1e10a5dd802e9c5999691e5 100755 +--- a/tools/install.py ++++ b/tools/install.py +@@ -117,26 +117,23 @@ def subdir_files(path, dest, action): + + def files(action): + is_windows = sys.platform == 'win32' +- output_file = 'node' + output_prefix = 'out/Release/' ++ output_libprefix = output_prefix + +- if 'false' == variables.get('node_shared'): +- if is_windows: +- output_file += '.exe' ++ if is_windows: ++ output_bin = 'node.exe' ++ output_lib = 'node.dll' + else: +- if is_windows: +- output_file += '.dll' +- else: +- output_file = 'lib' + output_file + '.' + variables.get('shlib_suffix') +- # GYP will output to lib.target except on OS X, this is hardcoded +- # in its source - see the _InstallableTargetInstallPath function. +- if sys.platform != 'darwin': +- output_prefix += 'lib.target/' ++ output_bin = 'node' ++ output_lib = 'libnode.' + variables.get('shlib_suffix') ++ # GYP will output to lib.target except on OS X, this is hardcoded ++ # in its source - see the _InstallableTargetInstallPath function. ++ if sys.platform != 'darwin': ++ output_libprefix += 'lib.target/' + +- if 'false' == variables.get('node_shared'): +- action([output_prefix + output_file], 'bin/' + output_file) +- else: +- action([output_prefix + output_file], 'lib/' + output_file) ++ action([output_prefix + output_bin], 'bin/' + output_bin) ++ if 'true' == variables.get('node_shared'): ++ action([output_libprefix + output_lib], variables.get('libdir') + '/' + output_lib) + + if 'true' == variables.get('node_use_dtrace'): + action(['out/Release/node.d'], 'lib/dtrace/node.d') +-- +2.24.1 + diff --git a/0003-build-auto-load-ICU-data-from-with-icu-default-data-.patch b/0003-build-auto-load-ICU-data-from-with-icu-default-data-.patch new file mode 100644 index 0000000000000000000000000000000000000000..9a02d6519c42ec29ba4d7acfec0eb7089c916caf --- /dev/null +++ b/0003-build-auto-load-ICU-data-from-with-icu-default-data-.patch @@ -0,0 +1,122 @@ +From 9ca4d4aeccf50e6c036e5536ef070a09c1776817 Mon Sep 17 00:00:00 2001 +From: Stephen Gallagher +Date: Fri, 6 Dec 2019 16:40:25 -0500 +Subject: [PATCH 3/3] build: auto-load ICU data from + --with-icu-default-data-dir + +When compiled with `--with-intl=small` and +`--with-icu-default-data-dir=PATH`, Node.js will use PATH as a +fallback location for the ICU data. + +We will first perform an access check using fopen(PATH, 'r') to +ensure that the file is readable. If it is, we'll set the +icu_data_directory and proceed. There's a slight overhead for the +fopen() check, but it should be barely measurable. + +This will be useful for Linux distribution packagers who want to +be able to ship a minimal node binary in a container image but +also be able to add on the full i18n support where needed. With +this patch, it becomes possible to ship the interpreter as +/usr/bin/node in one package for the distribution and to ship the +data files in another package (without a strict dependency +between the two). This means that users of the distribution will +not need to explicitly direct Node.js to locate the ICU data. It +also means that in environments where full internationalization is +not required, they do not need to carry the extra content (with +the associated storage costs). + +Refs: https://github.com/nodejs/node/issues/3460 + +Signed-off-by: Stephen Gallagher +--- + configure.py | 9 +++++++++ + node.gypi | 7 +++++++ + src/node.cc | 20 ++++++++++++++++++++ + 3 files changed, 36 insertions(+) + +diff --git a/configure.py b/configure.py +index 48389fbdcb57cbf8d9c11d4921c65f34a1937cc7..063e8748b954a7fed4fe084399e61371c061edab 100755 +--- a/configure.py ++++ b/configure.py +@@ -433,6 +433,14 @@ intl_optgroup.add_option('--with-icu-source', + 'the icu4c source archive. ' + 'v%d.x or later recommended.' % icu_versions['minimum_icu']) + ++intl_optgroup.add_option('--with-icu-default-data-dir', ++ action='store', ++ dest='with_icu_default_data_dir', ++ help='Path to the icuXXdt{lb}.dat file. If unspecified, ICU data will ' ++ 'only be read if the NODE_ICU_DATA environment variable or the ' ++ '--icu-data-dir runtime argument is used. This option has effect ' ++ 'only when Node.js is built with --with-intl=small-icu.') ++ + parser.add_option('--with-ltcg', + action='store_true', + dest='with_ltcg', +@@ -1360,6 +1368,7 @@ def configure_intl(o): + locs.add('root') # must have root + o['variables']['icu_locales'] = string.join(locs,',') + # We will check a bit later if we can use the canned deps/icu-small ++ o['variables']['icu_default_data'] = options.with_icu_default_data_dir or '' + elif with_intl == 'full-icu': + # full ICU + o['variables']['v8_enable_i18n_support'] = 1 +diff --git a/node.gypi b/node.gypi +index 466a1746811cfac1a8ce4ef604ef1152c6229ff1..65b97d6466a14f4343a948a5fc36f8a2580badfb 100644 +--- a/node.gypi ++++ b/node.gypi +@@ -113,6 +113,13 @@ + 'conditions': [ + [ 'icu_small=="true"', { + 'defines': [ 'NODE_HAVE_SMALL_ICU=1' ], ++ 'conditions': [ ++ [ 'icu_default_data!=""', { ++ 'defines': [ ++ 'NODE_ICU_DEFAULT_DATA_DIR="<(icu_default_data)"', ++ ], ++ }], ++ ], + }]], + }], + [ 'node_use_bundled_v8=="true" and \ +diff --git a/src/node.cc b/src/node.cc +index 7c0118758dfd9449283b900209b2ba8df7ddd129..c9840e3e367ca47176a17a7940a1e08eb1f56f78 100644 +--- a/src/node.cc ++++ b/src/node.cc +@@ -92,6 +92,7 @@ + + #if defined(NODE_HAVE_I18N_SUPPORT) + #include ++#include + #endif + + #if defined(LEAK_SANITIZER) +@@ -2643,6 +2644,25 @@ void Init(std::vector* argv, + // If the parameter isn't given, use the env variable. + if (per_process_opts->icu_data_dir.empty()) + SafeGetenv("NODE_ICU_DATA", &per_process_opts->icu_data_dir); ++ ++#ifdef NODE_ICU_DEFAULT_DATA_DIR ++ // If neither the CLI option nor the environment variable was specified, ++ // fall back to the configured default ++ if (per_process_opts->icu_data_dir.empty()) { ++ // Check whether the NODE_ICU_DEFAULT_DATA_DIR contains the right data ++ // file and can be read. ++ static const char full_path[] = ++ NODE_ICU_DEFAULT_DATA_DIR "/" U_ICUDATA_NAME ".dat"; ++ ++ FILE* f = fopen(full_path, "rb"); ++ ++ if (f != nullptr) { ++ fclose(f); ++ per_process_opts->icu_data_dir = NODE_ICU_DEFAULT_DATA_DIR; ++ } ++ } ++#endif // NODE_ICU_DEFAULT_DATA_DIR ++ + // Initialize ICU. + // If icu_data_dir is empty here, it will load the 'minimal' data. + if (!i18n::InitializeICUDirectory(per_process_opts->icu_data_dir)) { +-- +2.24.1 + diff --git a/0004-src-avoid-OOB-read-in-URL-parser.patch b/0004-src-avoid-OOB-read-in-URL-parser.patch new file mode 100644 index 0000000000000000000000000000000000000000..6108a397efe0aa1ec92b151657b57791d4537977 --- /dev/null +++ b/0004-src-avoid-OOB-read-in-URL-parser.patch @@ -0,0 +1,79 @@ +From 4cb8fa4aa5dea72bc66ea950e3fc193385bb7175 Mon Sep 17 00:00:00 2001 +From: gaozhekang +Date: Wed, 4 Nov 2020 11:12:53 +0800 +Subject: [PATCH] src: avoid OOB read in URL parser + +This is not a big concern, because right now, all (non-test) inputs +to the parser are `'\0'`-terminated, but we should be future-proof +here and not perform these OOB reads. + +--- + src/node_url.cc | 6 +++--- + test/cctest/test_url.cc | 20 ++++++++++++++++++++ + 2 files changed, 23 insertions(+), 3 deletions(-) + +diff --git a/src/node_url.cc b/src/node_url.cc +index 7bfcde5..41492b1 100644 +--- a/src/node_url.cc ++++ b/src/node_url.cc +@@ -1487,7 +1487,7 @@ void URL::Parse(const char* input, + state = kSpecialRelativeOrAuthority; + } else if (special) { + state = kSpecialAuthoritySlashes; +- } else if (p[1] == '/') { ++ } else if (p + 1 < end && p[1] == '/') { + state = kPathOrAuthority; + p++; + } else { +@@ -1547,7 +1547,7 @@ void URL::Parse(const char* input, + } + break; + case kSpecialRelativeOrAuthority: +- if (ch == '/' && p[1] == '/') { ++ if (ch == '/' && p + 1 < end && p[1] == '/') { + state = kSpecialAuthorityIgnoreSlashes; + p++; + } else { +@@ -1695,7 +1695,7 @@ void URL::Parse(const char* input, + break; + case kSpecialAuthoritySlashes: + state = kSpecialAuthorityIgnoreSlashes; +- if (ch == '/' && p[1] == '/') { ++ if (ch == '/' && p + 1 < end && p[1] == '/') { + p++; + } else { + continue; +diff --git a/test/cctest/test_url.cc b/test/cctest/test_url.cc +index ddef534..810cbc2 100644 +--- a/test/cctest/test_url.cc ++++ b/test/cctest/test_url.cc +@@ -80,6 +80,26 @@ TEST_F(URLTest, Base3) { + EXPECT_EQ(simple.path(), "/baz"); + } + ++TEST_F(URLTest, TruncatedAfterProtocol) { ++ char input[2] = { 'q', ':' }; ++ URL simple(input, sizeof(input)); ++ ++ EXPECT_FALSE(simple.flags() & URL_FLAGS_FAILED); ++ EXPECT_EQ(simple.protocol(), "q:"); ++ EXPECT_EQ(simple.host(), ""); ++ EXPECT_EQ(simple.path(), "/"); ++} ++ ++TEST_F(URLTest, TruncatedAfterProtocol2) { ++ char input[6] = { 'h', 't', 't', 'p', ':', '/' }; ++ URL simple(input, sizeof(input)); ++ ++ EXPECT_TRUE(simple.flags() & URL_FLAGS_FAILED); ++ EXPECT_EQ(simple.protocol(), "http:"); ++ EXPECT_EQ(simple.host(), ""); ++ EXPECT_EQ(simple.path(), ""); ++} ++ + TEST_F(URLTest, ToFilePath) { + #define T(url, path) EXPECT_EQ(path, URL(url).ToFilePath()) + T("http://example.org/foo/bar", ""); +-- +2.23.0 + diff --git a/CVE-2018-12122.patch b/CVE-2018-12122.patch deleted file mode 100644 index c46268b278865a2e9d773bfcc441a160c8f48b55..0000000000000000000000000000000000000000 --- a/CVE-2018-12122.patch +++ /dev/null @@ -1,208 +0,0 @@ -From ee618a7ab239c98d945c723a4e225bc409151736 Mon Sep 17 00:00:00 2001 -From: Matteo Collina -Date: Thu, 23 Aug 2018 16:46:07 +0200 -Subject: [PATCH] http,https: protect against slow headers attack - -CVE-2018-12122 - -An attacker can send a char/s within headers and exahust the resources -(file descriptors) of a system even with a tight max header length -protection. This PR destroys a socket if it has not received the headers -in 40s. - -PR-URL: https://github.com/nodejs-private/node-private/pull/144 -Reviewed-By: Sam Roberts -Reviewed-By: Ben Noordhuis -Reviewed-By: James M Snell ---- - doc/api/http.md | 20 ++++++++ - doc/api/https.md | 7 +++ - lib/_http_server.js | 22 ++++++++- - lib/https.js | 1 + - lib/internal/http.js | 27 +++++++--- - test/async-hooks/test-graph.http.js | 2 +- - test/parallel/test-http-slow-headers.js | 50 +++++++++++++++++++ - test/parallel/test-https-slow-headers.js | 63 ++++++++++++++++++++++++ - 8 files changed, 182 insertions(+), 10 deletions(-) - create mode 100644 test/parallel/test-http-slow-headers.js - create mode 100644 test/parallel/test-https-slow-headers.js - -diff --git a/doc/api/http.md b/doc/api/http.md -index 1c6b5717e004..13373debb404 100644 ---- a/doc/api/http.md -+++ b/doc/api/http.md -@@ -958,6 +958,26 @@ added: v0.7.0 - - Limits maximum incoming headers count. If set to 0, no limit will be applied. - -+### server.headersTimeout -+ -+ -+* {number} **Default:** `40000` -+ -+Limit the amount of time the parser will wait to receive the complete HTTP -+headers. -+ -+In case of inactivity, the rules defined in [server.timeout][] apply. However, -+that inactivity based timeout would still allow the connection to be kept open -+if the headers are being sent very slowly (by default, up to a byte per 2 -+minutes). In order to prevent this, whenever header data arrives an additional -+check is made that more than `server.headersTimeout` milliseconds has not -+passed since the connection was established. If the check fails, a `'timeout'` -+event is emitted on the server object, and (by default) the socket is destroyed. -+See [server.timeout][] for more information on how timeout behaviour can be -+customised. -+ - ### server.setTimeout([msecs][, callback]) -