Skip to content

Commit

Permalink
avoid regex for tag content footgun (#89)
Browse files Browse the repository at this point in the history
using regex to try to select the content fo the table was leading to runaway catastprohic backtracking.

the simple solution is to just do string substring selection and insertion on the start and end tag
  • Loading branch information
theinterned authored Aug 10, 2023
1 parent 7186fa0 commit 6657ec6
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 2 deletions.
10 changes: 9 additions & 1 deletion src/paste-markdown-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ function generateText(transfer: DataTransfer): string | undefined {
const html = transfer.getData('text/html')
if (!/<table/i.test(html)) return

// eslint-disable-next-line github/unescaped-html-literal
const start = html.substring(0, html.indexOf('<table'))
const tableCloseIndex = html.lastIndexOf('</table>')
if (!start || !tableCloseIndex) return
const end = html.substring(tableCloseIndex + 8)

const parser = new DOMParser()
const parsedDocument = parser.parseFromString(html, 'text/html')

Expand All @@ -100,5 +106,7 @@ function generateText(transfer: DataTransfer): string | undefined {

const formattedTable = tableMarkdown(table)

return html.replace(/<meta.*?>/, '').replace(/<table[.\S\s]*<\/table>/, `\n${formattedTable}`)
if (!formattedTable) return

return [start, formattedTable, end].join('').replace(/<meta.*?>/, '')
}
15 changes: 14 additions & 1 deletion test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ describe('paste-markdown', function () {
assert.equal(
textarea.value.trim(),
// eslint-disable-next-line github/unescaped-html-literal
`<p>Here is a cool table</p>\n \n \n\n${tableMarkdown}\n\n\n\n <p>Very cool</p>`
`<p>Here is a cool table</p>\n \n \n${tableMarkdown}\n\n\n\n <p>Very cool</p>`
)
})

Expand All @@ -225,6 +225,19 @@ describe('paste-markdown', function () {
assertUnformattedPaste(textarea)
})

it('rejects malformed tables', function () {
// eslint-disable-next-line github/unescaped-html-literal, prefer-template
const html = '<table'.repeat(999) + '<div><table></div>'
const data = {
'text/html': html
}
paste(textarea, data)

// Synthetic paste events don't manipulate the DOM. A empty textarea
// means that the event handler didn't fire and normal paste happened.
assertUnformattedPaste(textarea)
})

it('accepts x-gfm', function () {
paste(textarea, {'text/plain': 'hello', 'text/x-gfm': '# hello'})
assert.include(textarea.value, '# hello')
Expand Down

0 comments on commit 6657ec6

Please sign in to comment.