Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix backtick for code in links #1794

Closed

Conversation

pgcalixto
Copy link

Previously, when there as an inline code as a link label, it would only work if the backticks were single-opened and single-closed
(as in 1 backtick opening the code block + 1 backtick closing the code block).

Now one can use more than 1 backtick to open/close the inline code block as a link label.

Marked version: 1.2.2

Markdown flavor: GitHub Flavored Markdown

Description

Expectation

Links should support having inline code blocks opened with multiple backticks (2nd link in the example below). Even if the backtick closes the code block, there still should be a link (3rd link in the example below).

image

Reference:

https://spec.commonmark.org/dingus/?text=start%20links%0A%0A%5B%60%20this%20is%20a%20backtick%20and%20it%20does%20not%20break%20stuff%20%60%5D(https%3A%2F%2Fexample.com)%0A%0A%5B%60%60%20this%20is%20a%20backtick%20%60%20and%20it%20breaks%20stuff%20%60%60%5D(https%3A%2F%2Fexample.com)%0A%0A%5B%60%20this%20is%20a%20backtick%20%60%20which%20stops%20being%20code%20but%20is%20still%20a%20link%60%5D(https%3A%2F%2Fexample.com)%0A%0Aend%20links%0A%0A

(I included the screenshot because the custom commonmark URL only seems to work on Chrome, not Firefox)

Result

Marked, however, does not support the scenarios described above. It only supports code blocks in links when they are opened with a single backtick and closed with a single backtick.

Reference:

https://marked.js.org/demo/?text=start%20links%0A%0A%5B%60%20this%20is%20a%20backtick%20and%20it%20does%20not%20break%20stuff%20%60%5D(https%3A%2F%2Fexample.com)%0A%0A%5B%60%60%20this%20is%20a%20backtick%20%60%20and%20it%20breaks%20stuff%20%60%60%5D(https%3A%2F%2Fexample.com)%0A%0A%5B%60%20this%20is%20a%20backtick%20%60%20which%20stops%20being%20code%20but%20is%20still%20a%20link%60%5D(https%3A%2F%2Fexample.com)%0A%0Aend%20links%0A&options=%7B%0A%20%22baseUrl%22%3A%20null%2C%0A%20%22breaks%22%3A%20false%2C%0A%20%22gfm%22%3A%20true%2C%0A%20%22headerIds%22%3A%20true%2C%0A%20%22headerPrefix%22%3A%20%22%22%2C%0A%20%22highlight%22%3A%20null%2C%0A%20%22langPrefix%22%3A%20%22language-%22%2C%0A%20%22mangle%22%3A%20true%2C%0A%20%22pedantic%22%3A%20false%2C%0A%20%22sanitize%22%3A%20false%2C%0A%20%22sanitizer%22%3A%20null%2C%0A%20%22silent%22%3A%20false%2C%0A%20%22smartLists%22%3A%20false%2C%0A%20%22smartypants%22%3A%20false%2C%0A%20%22tokenizer%22%3A%20null%2C%0A%20%22xhtml%22%3A%20false%0A%7D&version=master

What was attempted

Now, instead of matching only a single-opening backtick + no backticks + single-closing backtick, as in `[^`]*`, anything can be matched inside the backticks, as in `.*`.

It correctly parsed the links, as shown below when I ran it locally:

image

Contributor

  • Test(s) exist to ensure functionality and minimize regression (if no tests added, list tests covering this PR); or,
  • no tests required for this PR.
  • If submitting new feature, it has been documented in the appropriate places.

Committer

In most cases, this should be a different person than the contributor.

Previously, when there as an inline code as a link label, it would
only work if the backticks were single-opened and single-closed
(as in 1 backtick opening the code block + 1 backtick closing the
code block).
Now one can use more than 1 backtick to open/close the inline code
block as a link label.

Closes markedjs#1663.
@vercel
Copy link

vercel bot commented Oct 22, 2020

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/markedjs/markedjs/72ab2seya
✅ Preview: https://markedjs-git-fix-backtick-in-code-link.markedjs.vercel.app

@UziTech
Copy link
Member

UziTech commented Oct 22, 2020

looks like this introduces a ReDos vulnerability.

POC

const marked = require('marked');

let count = 30;
while (count < 100) {
  const start = Date.now();
  marked('[` ' + '`'.repeat(count) + ' `]');
  const duration = Date.now() - start;
  console.log(`${count}: ${duration}ms`);
  if (duration > 2000) {
    break;
  }
  count += 1;
}

// 30: 74ms
// 31: 106ms
// 32: 163ms
// 33: 255ms
// 34: 383ms
// 35: 613ms
// 36: 985ms
// 37: 1594ms
// 38: 2553ms

@UziTech
Copy link
Member

UziTech commented Oct 22, 2020

In order to fix this without introducing vulnerabilities we will probably need to make this regex more inclusive then update the tokenizer to weed out the false positives. Probably something similar to the way strong and em were fixed in #1686.

@calculuschild
Copy link
Contributor

calculuschild commented Oct 22, 2020

@pgcalixto Unless you make changes elsewhere like in the Tokenizer maybe, you need to keep the [^`]* part in there (anything can go between backticks except more backticks) or regex has to start making tons of extra checks if it is really at the end of the link or not.

In the meantime, maybe a simple (but not all-inclusive) solution might I suggest just adding in a second case that has two backticks on each end like so? The GFM spec only ever seems to show a maximum of 2 backticks in the examples, although technically more would be valid...

``[^`]*``|`[^`]*`

@UziTech
Copy link
Member

UziTech commented Nov 12, 2021

I'm closing this as stale. If you want to reopen it and continue the progress feel free.

@UziTech UziTech closed this Nov 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

A backtick in code in a link parses incorrectly
3 participants