fix: Avoid O(n^2) backtracking in inline link href regex#4013
Merged
Conversation
|
@hong4rc is attempting to deploy a commit to the MarkedJS Team on Vercel. A member of the Team first needs to authorize it. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
github-actions Bot
pushed a commit
that referenced
this pull request
Jul 9, 2026
## [18.0.6](v18.0.5...v18.0.6) (2026-07-09) ### Bug Fixes * Avoid O(n^2) backtracking in inline link href regex ([#4013](#4013)) ([a009808](a009808)) * Fix ordered lists after blockquotes ([#4003](#4003)) ([33928d0](33928d0)) * keep trailing text on HTML block close line for PI, declarations, and CDATA ([#3991](#3991)) ([bbb84c8](bbb84c8))
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Marked version: current
master(regex unchanged since 18.0.5)Markdown flavor: n/a
Description
The inline link regex parses an unclosed link followed by a long whitespace run in O(n²) time.
marked.parse('[](' + ' '.repeat(n))is just text — an unclosed link — but with default options the parse time roughly quadruples each time the input doubles: n=16,000 → ~0.3 s, 32,000 → ~1.2 s, 64,000 → ~4.9 s, 125,000 → ~21 s.The cause is the unquoted-href alternative
[^ \t\n\x00-\x1f]*insrc/rules.ts. Since it can match empty at any whitespace position, when there is no closing)the leading\s*, the (empty) href, the optional title separator, and the trailing\s*\)all re-partition the same whitespace run at ~n positions, so the engine backtracks quadratically. #3902 hardened the title separator ([ \t]*→[ \t]+|\n) against the same class of problem but left this zero-length href branch, so input that never reaches the title branch still backtracks.The fix requires the unquoted-href branch to match at least one non-whitespace character (
*→+) and keeps the legitimate empty-href case[foo]()via a(?=\))lookahead. CommonMark specifies that an unquoted link destination ends at whitespace, so requiring ≥1 non-whitespace character there is spec-correct. After the change the same input parses in linear time (64 KB → ~1 ms) and ordinary links are unaffected: the full spec and unit suites stay green (test:specs1749/0,test:unit188/0), and I addedtest/specs/redos/quadratic_link_empty_href.cjsnext to the existing quadratic guards so any regression fails fast.Contributor
test/specs/redos/quadratic_link_empty_href.cjs.