From 0ead788ac9fb829cb6772eeb35d2974d25091dd9 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Mon, 6 May 2024 13:24:52 +0200 Subject: [PATCH 1/4] fix(arg-parser): address regexp perf warnings for URI parsing I --- packages/arg-parser/src/uri-generator.ts | 60 +++++++++++------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/packages/arg-parser/src/uri-generator.ts b/packages/arg-parser/src/uri-generator.ts index 7fc1be56d..4eae41287 100644 --- a/packages/arg-parser/src/uri-generator.ts +++ b/packages/arg-parser/src/uri-generator.ts @@ -107,15 +107,11 @@ function validateHost(host: string): void { * returns an individual `:` array. */ function validateHostSeedList( - hosts: string, + hosts: string[], fixedPort: string | undefined ): string[] { - const trimmedHosts = hosts - .split(',') - .map((h) => h.trim()) - .filter((h) => !!h); const hostList: string[] = []; - for (const h of trimmedHosts) { + for (const h of hosts) { // Split at the last colon to separate the port from the host // (if that colon is followed exclusively by digits) const { host, port } = @@ -175,6 +171,26 @@ function generatePort(options: CliOptions): string { return options.port ? options.port : DEFAULT_PORT; } +function parseHostOption(value: string | undefined): { + replSetName?: string; + hosts?: string[]; +} { + // Parse [/][<:port>][,[<:port>][,<...>]] + if (!value) return {}; + // replSetName is optional and we only allow one slash in the whole string at most + const [hostList, replSetName, ...rest] = value.split('/').reverse(); + if (rest.length) return {}; + const hosts = hostList.split(',').filter(Boolean); + // All hosts follow the pattern (hostname|ipv4|ipv6)[(:port)] + if ( + !hosts.every((host) => + /^([A-Za-z0-9._-]+|\[[0-9a-fA-F:]+\])(:\d+)?$/.test(host) + ) + ) + return {}; + return { replSetName, hosts }; +} + /** * Generate a URI from the provided CLI options. * @@ -208,36 +224,16 @@ export function generateUri(options: Readonly): string { function generateUriNormalized(options: CliOptions): ConnectionString { const uri = options.connectionSpecifier; - // If the --host argument contains /, it has the format - // /<:port>,<:port>,<...> - const replSetHostMatch = - /^(?[^/]+)\/(?(([A-Za-z0-9._-]+|\[[0-9a-fA-F:]+\])(:\d+)?,?)+)$/.exec( - options.host ?? '' - ); - if (replSetHostMatch) { - const { replSetName, hosts } = replSetHostMatch.groups as { - replSetName: string; - hosts: string; - }; - const connectionString = new ConnectionString( - `mongodb://replacemeHost/${encodeURIComponent(uri || '')}` - ); - connectionString.hosts = validateHostSeedList(hosts, options.port); - connectionString.searchParams.set('replicaSet', replSetName); - return addShellConnectionStringParameters(connectionString); - } - - // If the --host argument contains multiple hosts as a seed list - // we directly do not do additional host/port parsing - const seedList = /^(?([A-Za-z0-9._-]+(:\d+)?,?)+)$/.exec( - options.host ?? '' - ); - if (seedList && options.host?.includes(',')) { - const { hosts } = seedList.groups as { hosts: string }; + // The --host argument has the format + // [/][<:port>][,[<:port>][,<...>]] + const { replSetName, hosts } = parseHostOption(options.host); + if (hosts) { const connectionString = new ConnectionString( `mongodb://replacemeHost/${encodeURIComponent(uri || '')}` ); connectionString.hosts = validateHostSeedList(hosts, options.port); + if (replSetName) + connectionString.searchParams.set('replicaSet', replSetName); return addShellConnectionStringParameters(connectionString); } From 07063b6ce5fdfa2f345db11919d4d3f2308b256f Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Mon, 6 May 2024 13:28:43 +0200 Subject: [PATCH 2/4] fix(arg-parser): address regexp perf warnings for URI parsing II --- packages/arg-parser/src/uri-generator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/arg-parser/src/uri-generator.ts b/packages/arg-parser/src/uri-generator.ts index 4eae41287..555334f32 100644 --- a/packages/arg-parser/src/uri-generator.ts +++ b/packages/arg-parser/src/uri-generator.ts @@ -260,7 +260,7 @@ function generateUriNormalized(options: CliOptions): ConnectionString { // Capture host, port and db from the string and generate a URI from // the parts. If there is a db part, it *must* start with /. - const uriMatch = /^([A-Za-z0-9][A-Za-z0-9._-]+):?(\d+)?(?:\/(\S*))?$/gi; + const uriMatch = /^([A-Za-z0-9][A-Za-z0-9._-]+)(?::(\d+))?(?:\/(\S*))?$/gi; let parts: string[] | null = uriMatch.exec(uri); if (parts === null) { From 8687750e23375d4e8d110b37bae5d1ca70d8062b Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Mon, 6 May 2024 13:34:15 +0200 Subject: [PATCH 3/4] fix(editor): address regexp perf warnings for URI parsing III --- packages/editor/src/editor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/editor.ts b/packages/editor/src/editor.ts index fd0173046..f98cec01c 100644 --- a/packages/editor/src/editor.ts +++ b/packages/editor/src/editor.ts @@ -145,7 +145,7 @@ export class Editor { } _isVscodeApp(cmd: string): boolean { - const regex = /^(.*)[/\\]?[cC]ode(.exe)?(\s(.*))?$/; + const regex = /[/\\]?[cC]ode(.exe)?(\s|$)/; return regex.test(cmd); } From 70dcadb59f89c9e3e8bc2acc6bc89c15da321090 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Mon, 6 May 2024 16:26:07 +0200 Subject: [PATCH 4/4] fixup --- packages/arg-parser/src/uri-generator.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/arg-parser/src/uri-generator.ts b/packages/arg-parser/src/uri-generator.ts index 555334f32..6454aa7d9 100644 --- a/packages/arg-parser/src/uri-generator.ts +++ b/packages/arg-parser/src/uri-generator.ts @@ -186,8 +186,9 @@ function parseHostOption(value: string | undefined): { !hosts.every((host) => /^([A-Za-z0-9._-]+|\[[0-9a-fA-F:]+\])(:\d+)?$/.test(host) ) - ) + ) { return {}; + } return { replSetName, hosts }; } @@ -227,11 +228,11 @@ function generateUriNormalized(options: CliOptions): ConnectionString { // The --host argument has the format // [/][<:port>][,[<:port>][,<...>]] const { replSetName, hosts } = parseHostOption(options.host); - if (hosts) { + if (replSetName || (hosts ?? []).length > 1) { const connectionString = new ConnectionString( `mongodb://replacemeHost/${encodeURIComponent(uri || '')}` ); - connectionString.hosts = validateHostSeedList(hosts, options.port); + connectionString.hosts = validateHostSeedList(hosts ?? [], options.port); if (replSetName) connectionString.searchParams.set('replicaSet', replSetName); return addShellConnectionStringParameters(connectionString);