From 4402973196ca3b790dce34f3b0e46cefbf21b139 Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Thu, 18 Jan 2024 22:16:56 +0000 Subject: [PATCH 1/2] Add explainer for glob regex pattern --- rules/embeds/glob.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rules/embeds/glob.js b/rules/embeds/glob.js index e236792..a48eb8b 100644 --- a/rules/embeds/glob.js +++ b/rules/embeds/glob.js @@ -78,7 +78,9 @@ module.exports = md => { if (closingMark === -1) return false; // Check for glob match - const match = currentLines.slice(0, closingMark + 3).match(/^\[glob (.+?(?:(?: [^ \n]+?)+|(?:\n.+?)+))\](?:$|\n)/); + // .+(?:\n.+)+ allows for a glob with spaces on the first line, and then tests separated by newlines + // [^ \n]+(?: [^ \n]+)+ allows for a glob with no spaces on the first line, and then tests separated by spaces + const match = currentLines.slice(0, closingMark + 3).match(/^\[glob (.+(?:\n.+)+|[^ \n]+(?: [^ \n]+)+)\](?:$|\n)/); if (!match) return false; // Get the full strings From b9fb4829e5d39e8568cfa6ece45392173fdeb2d4 Mon Sep 17 00:00:00 2001 From: MattIPv4 Date: Thu, 18 Jan 2024 22:17:33 +0000 Subject: [PATCH 2/2] Switch to encodeURIComponent for glob URL generation --- CHANGELOG.md | 2 ++ rules/embeds/glob.js | 6 +++--- rules/embeds/glob.test.js | 16 +++++++++++++--- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5853e57..f10d79c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ Any non-code changes should be prefixed with `(docs)`. See `PUBLISH.md` for instructions on how to publish a new version. --> +- (patch) Avoid slowdown from `URL#searchParams` in glob embed + ## v1.12.1 - 39a3836 diff --git a/rules/embeds/glob.js b/rules/embeds/glob.js index a48eb8b..53f8a62 100644 --- a/rules/embeds/glob.js +++ b/rules/embeds/glob.js @@ -149,9 +149,9 @@ module.exports = md => { const tests = token.glob.tests.map((x, i) => `data-glob-test-${i}="${md.utils.escapeHtml(x)}"`).join(' '); // Construct the fallback URL - const url = new URL('https://www.digitalocean.com/community/tools/glob'); - url.searchParams.append('glob', token.glob.glob); - token.glob.tests.forEach(x => url.searchParams.append('tests', x)); + // Don't use URL#searchParams because it is very slow for large numbers of params + // https://twitter.com/MattIPv4/status/1748102513646047584 + const url = `https://www.digitalocean.com/community/tools/glob?glob=${encodeURIComponent(token.glob.glob)}${token.glob.tests.map(x => `&tests=${encodeURIComponent(x)}`).join('')}`; // Return the HTML return `
diff --git a/rules/embeds/glob.test.js b/rules/embeds/glob.test.js index 7b9ca24..e0cb5e4 100644 --- a/rules/embeds/glob.test.js +++ b/rules/embeds/glob.test.js @@ -60,7 +60,7 @@ it('handles glob embeds with linebreaks', () => { it('handles glob embeds with linebreaks and spaces in glob', () => { expect(md.render('[glob * test.js\n/a\n/b]')).toBe(`
- + Explore * test.js as a glob string in our glob testing tool
@@ -68,9 +68,19 @@ it('handles glob embeds with linebreaks and spaces in glob', () => { `); }); -it('handles glob embeds with many spaces in glob and a linebreak (ReDos)', () => { +it('handles glob embeds with many spaces in glob (DoS)', () => { + expect(md.render(`[glob ${Array.from('a'.repeat(50000)).join(' ')}]`)).toBe(`
`data-glob-test-${i}="${a}"`).join(' ')}> + + Explore a as a glob string in our glob testing tool + +
+ +`); +}); + +it('handles glob embeds with many spaces in glob and a linebreak (ReDoS)', () => { expect(md.render(`[glob ${Array.from('a'.repeat(50)).join(' ')}\nb\nc]`)).toBe(`
- + Explore ${Array.from('a'.repeat(50)).join(' ')} as a glob string in our glob testing tool