From fa8b7ba5ac5f08be8035f7651ed345514344d385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCrg=C3=BCn=20Day=C4=B1o=C4=9Flu?= Date: Sun, 16 Mar 2025 16:43:34 +0100 Subject: [PATCH 1/4] lib: limit split function calls to prevent excessive array length --- lib/internal/blob.js | 2 +- lib/internal/debugger/inspect.js | 2 +- lib/internal/errors.js | 2 +- lib/internal/modules/cjs/loader.js | 2 +- lib/internal/modules/esm/module_job.js | 2 +- lib/internal/repl/await.js | 2 +- lib/internal/source_map/source_map_cache.js | 2 +- lib/internal/test_runner/utils.js | 2 +- lib/internal/tty.js | 2 +- lib/internal/util/debuglog.js | 1 + lib/internal/worker/js_transferable.js | 2 +- 11 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/internal/blob.js b/lib/internal/blob.js index 6a526de7bfeb73..f27992eb2dcdfd 100644 --- a/lib/internal/blob.js +++ b/lib/internal/blob.js @@ -360,7 +360,7 @@ function resolveObjectURL(url) { try { const parsed = new URL(url); - const split = StringPrototypeSplit(parsed.pathname, ':'); + const split = StringPrototypeSplit(parsed.pathname, ':', 3); if (split.length !== 2) return; diff --git a/lib/internal/debugger/inspect.js b/lib/internal/debugger/inspect.js index 5e93699f8ba078..75636b159ede2e 100644 --- a/lib/internal/debugger/inspect.js +++ b/lib/internal/debugger/inspect.js @@ -160,7 +160,7 @@ class NodeInspector { this[domain] = createAgentProxy(domain, this.client); }); this.handleDebugEvent = (fullName, params) => { - const { 0: domain, 1: name } = StringPrototypeSplit(fullName, '.'); + const { 0: domain, 1: name } = StringPrototypeSplit(fullName, '.', 2); if (domain in this) { this[domain].emit(name, params); } diff --git a/lib/internal/errors.js b/lib/internal/errors.js index a0a39de45b2a59..87200b40d45bdc 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -907,7 +907,7 @@ const fatalExceptionStackEnhancers = { // ANSI escape sequences is not reliable. if (isWindows) { const info = internalBinding('os').getOSInformation(); - const ver = ArrayPrototypeMap(StringPrototypeSplit(info[2], '.'), + const ver = ArrayPrototypeMap(StringPrototypeSplit(info[2], '.', 3), Number); if (ver[0] !== 10 || ver[2] < 14393) { useColors = false; diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 96455306f3696d..be4bedeb12a535 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -1833,7 +1833,7 @@ function reconstructErrorStack(err, parentPath, parentSource) { const { 1: line, 2: col } = RegExpPrototypeExec(/(\d+):(\d+)\)/, errLine) || []; if (line && col) { - const srcLine = StringPrototypeSplit(parentSource, '\n')[line - 1]; + const srcLine = StringPrototypeSplit(parentSource, '\n', line)[line - 1]; const frame = `${parentPath}:${line}\n${srcLine}\n${StringPrototypeRepeat(' ', col - 1)}^\n`; setArrowMessage(err, frame); } diff --git a/lib/internal/modules/esm/module_job.js b/lib/internal/modules/esm/module_job.js index 7c83e58f7b7ee6..f33dc937102dc2 100644 --- a/lib/internal/modules/esm/module_job.js +++ b/lib/internal/modules/esm/module_job.js @@ -218,7 +218,7 @@ class ModuleJob extends ModuleJobBase { if (!getSourceMapsSupport().enabled && StringPrototypeIncludes(e.message, ' does not provide an export named')) { - const splitStack = StringPrototypeSplit(e.stack, '\n'); + const splitStack = StringPrototypeSplit(e.stack, '\n', 2); const parentFileUrl = RegExpPrototypeSymbolReplace( /:\d+$/, splitStack[0], diff --git a/lib/internal/repl/await.js b/lib/internal/repl/await.js index 9bdb834ff84fd7..1252df343334f5 100644 --- a/lib/internal/repl/await.js +++ b/lib/internal/repl/await.js @@ -178,7 +178,7 @@ function processTopLevelAwait(src) { return null; const line = e.loc.line; const column = line === 1 ? e.loc.column - wrapPrefix.length : e.loc.column; - let message = '\n' + StringPrototypeSplit(src, '\n')[line - 1] + '\n' + + let message = '\n' + StringPrototypeSplit(src, '\n', line)[line - 1] + '\n' + StringPrototypeRepeat(' ', column) + '^\n\n' + RegExpPrototypeSymbolReplace(/ \([^)]+\)/, e.message, ''); // V8 unexpected token errors include the token string. diff --git a/lib/internal/source_map/source_map_cache.js b/lib/internal/source_map/source_map_cache.js index bdef338e3dd086..639051ec10fe61 100644 --- a/lib/internal/source_map/source_map_cache.js +++ b/lib/internal/source_map/source_map_cache.js @@ -292,7 +292,7 @@ function sourceMapFromFile(mapURL) { // data:[][;base64], see: // https://tools.ietf.org/html/rfc2397#section-2 function sourceMapFromDataUrl(sourceURL, url) { - const { 0: format, 1: data } = StringPrototypeSplit(url, ','); + const { 0: format, 1: data } = StringPrototypeSplit(url, ',', 2); const splitFormat = StringPrototypeSplit(format, ';'); const contentType = splitFormat[0]; const base64 = splitFormat[splitFormat.length - 1] === 'base64'; diff --git a/lib/internal/test_runner/utils.js b/lib/internal/test_runner/utils.js index 6a2ded4cd53b30..0fdd858fd94e28 100644 --- a/lib/internal/test_runner/utils.js +++ b/lib/internal/test_runner/utils.js @@ -263,7 +263,7 @@ function parseCommandLine() { ); } - const indexAndTotal = StringPrototypeSplit(shardOption, '/'); + const indexAndTotal = StringPrototypeSplit(shardOption, '/', 2); shard = { __proto__: null, index: NumberParseInt(indexAndTotal[0], 10), diff --git a/lib/internal/tty.js b/lib/internal/tty.js index b0bfac122781cc..486c2d06e7e9b8 100644 --- a/lib/internal/tty.js +++ b/lib/internal/tty.js @@ -138,7 +138,7 @@ function getColorDepth(env = process.env) { // Lazy load for startup performance. if (OSRelease === undefined) { const { release } = require('os'); - OSRelease = StringPrototypeSplit(release(), '.'); + OSRelease = StringPrototypeSplit(release(), '.', 3); } // Windows 10 build 10586 is the first Windows release that supports 256 // colors. Windows 10 build 14931 is the first release that supports diff --git a/lib/internal/util/debuglog.js b/lib/internal/util/debuglog.js index 96b10c4bbac767..919ab97f11547e 100644 --- a/lib/internal/util/debuglog.js +++ b/lib/internal/util/debuglog.js @@ -160,6 +160,7 @@ function formatTime(ms) { ({ 0: seconds, 1: ms } = StringPrototypeSplit( NumberPrototypeToFixed(seconds, 3), '.', + 2, )); const res = hours !== 0 ? `${hours}:${pad(minutes)}` : minutes; return `${res}:${pad(seconds)}.${ms} (${hours !== 0 ? 'h:m' : ''}m:ss.mmm)`; diff --git a/lib/internal/worker/js_transferable.js b/lib/internal/worker/js_transferable.js index 592d43d2152e0a..b830c161bbf556 100644 --- a/lib/internal/worker/js_transferable.js +++ b/lib/internal/worker/js_transferable.js @@ -35,7 +35,7 @@ function setup() { // from .postMessage() calls. The format of `deserializeInfo` is generally // 'module:Constructor', e.g. 'internal/fs/promises:FileHandle'. setDeserializerCreateObjectFunction((deserializeInfo) => { - const { 0: module, 1: ctor } = StringPrototypeSplit(deserializeInfo, ':'); + const { 0: module, 1: ctor } = StringPrototypeSplit(deserializeInfo, ':', 2); const Ctor = require(module)[ctor]; if (typeof Ctor !== 'function' || typeof Ctor.prototype[messaging_deserialize_symbol] !== 'function') { From 3afa0aaf8689d62793acb21dee8e2180b4ca1a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCrg=C3=BCn=20Day=C4=B1o=C4=9Flu?= Date: Sun, 16 Mar 2025 17:05:16 +0100 Subject: [PATCH 2/4] add limit to patternSubdomain split --- lib/tls.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tls.js b/lib/tls.js index 06a6695034d8a0..91ea8ad65a395c 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -254,7 +254,7 @@ function check(hostParts, pattern, wildcards) { const hostSubdomain = hostParts[0]; const patternSubdomain = patternParts[0]; - const patternSubdomainParts = patternSubdomain.split('*'); + const patternSubdomainParts = patternSubdomain.split('*', 3); // Short-circuit when the subdomain does not contain a wildcard. // RFC 6125 does not allow wildcard substitution for components From 15a414ed78d7e00dd1f9125607177a3e6812fde8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCrg=C3=BCn=20Day=C4=B1o=C4=9Flu?= Date: Sun, 16 Mar 2025 20:06:50 +0100 Subject: [PATCH 3/4] add split limit to url and punycode --- lib/punycode.js | 2 +- lib/url.js | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/punycode.js b/lib/punycode.js index e303a5373b8839..7cc4df6a88567d 100644 --- a/lib/punycode.js +++ b/lib/punycode.js @@ -82,7 +82,7 @@ function map(array, callback) { * function. */ function mapDomain(domain, callback) { - const parts = domain.split('@'); + const parts = domain.split('@', 2); let result = ''; if (parts.length > 1) { // In email addresses, only the domain name should be punycoded. Leave diff --git a/lib/url.js b/lib/url.js index c23d9c51c20033..59a639741497f3 100644 --- a/lib/url.js +++ b/lib/url.js @@ -886,10 +886,10 @@ Url.prototype.resolveObject = function resolveObject(relative) { // This especially happens in cases like // url.resolveObject('mailto:local1@domain1', 'local2@domain2') const authInHost = - result.host && result.host.indexOf('@') > 0 && result.host.split('@'); + result.host && result.host.indexOf('@') > 0 && result.host.split('@', 2); if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); + result.auth = authInHost[0]; + result.host = result.hostname = authInHost[1]; } } result.search = relative.search; @@ -966,11 +966,10 @@ Url.prototype.resolveObject = function resolveObject(relative) { // Occasionally the auth can get stuck only in host. // This especially happens in cases like // url.resolveObject('mailto:local1@domain1', 'local2@domain2') - const authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; + const authInHost = result.host && result.host.indexOf('@') > 0 && result.host.split('@', 2); if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); + result.auth = authInHost[0]; + result.host = result.hostname = authInHost[1]; } } From 4aa870e02a8680b13f98fc3697bb7e085b54148b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCrg=C3=BCn=20Day=C4=B1o=C4=9Flu?= Date: Sun, 16 Mar 2025 23:15:31 +0100 Subject: [PATCH 4/4] Revert "add split limit to url and punycode" This reverts commit 15a414ed78d7e00dd1f9125607177a3e6812fde8. --- lib/punycode.js | 2 +- lib/url.js | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/punycode.js b/lib/punycode.js index 7cc4df6a88567d..e303a5373b8839 100644 --- a/lib/punycode.js +++ b/lib/punycode.js @@ -82,7 +82,7 @@ function map(array, callback) { * function. */ function mapDomain(domain, callback) { - const parts = domain.split('@', 2); + const parts = domain.split('@'); let result = ''; if (parts.length > 1) { // In email addresses, only the domain name should be punycoded. Leave diff --git a/lib/url.js b/lib/url.js index 59a639741497f3..c23d9c51c20033 100644 --- a/lib/url.js +++ b/lib/url.js @@ -886,10 +886,10 @@ Url.prototype.resolveObject = function resolveObject(relative) { // This especially happens in cases like // url.resolveObject('mailto:local1@domain1', 'local2@domain2') const authInHost = - result.host && result.host.indexOf('@') > 0 && result.host.split('@', 2); + result.host && result.host.indexOf('@') > 0 && result.host.split('@'); if (authInHost) { - result.auth = authInHost[0]; - result.host = result.hostname = authInHost[1]; + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); } } result.search = relative.search; @@ -966,10 +966,11 @@ Url.prototype.resolveObject = function resolveObject(relative) { // Occasionally the auth can get stuck only in host. // This especially happens in cases like // url.resolveObject('mailto:local1@domain1', 'local2@domain2') - const authInHost = result.host && result.host.indexOf('@') > 0 && result.host.split('@', 2); + const authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; if (authInHost) { - result.auth = authInHost[0]; - result.host = result.hostname = authInHost[1]; + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); } }