Summary
The parser gets stuck in an infinite loop when a blockquote line contains U+2028 (line separator) or U+2029 (paragraph separator).
Environment
@tanstack/markdown 1.0.0 (main at d9b5ef7)
- Node v26.8.1
- The bug is in the parser so every renderer is affected.
Steps to reproduce
import { renderHtml } from '@tanstack/markdown/html'
renderHtml('>x') // returns
renderHtml('>x\u2028') // loops indefinitely
renderHtml('>x\u2029') // loops indefinitely
Root cause
parseBlockquote checks each line twice:
/^ {0,3}>\s?/ checks that the line starts a blockquote. >x\u2028 passes.
/^ {0,3}>\s?(.*)$/ reads the rest of the line. >x\u2028 fails.
The second check fails because JavaScript treats U+2028 and U+2029 as line breaks and . does not match a line break. So (.*) stops before the character and $ cannot match.
When the second check fails the loop exits before moving to the next line. The parser returns an empty blockquote without consuming the line. Then it tries the same line again forever.
Any line that starts with > and contains one of these characters triggers the bug. One exception: >\u2028x works because \s? takes the character right after >.
Summary
The parser gets stuck in an infinite loop when a blockquote line contains U+2028 (line separator) or U+2029 (paragraph separator).
Environment
@tanstack/markdown1.0.0 (mainatd9b5ef7)Steps to reproduce
Root cause
parseBlockquotechecks each line twice:/^ {0,3}>\s?/checks that the line starts a blockquote.>x\u2028passes./^ {0,3}>\s?(.*)$/reads the rest of the line.>x\u2028fails.The second check fails because JavaScript treats U+2028 and U+2029 as line breaks and
.does not match a line break. So(.*)stops before the character and$cannot match.When the second check fails the loop exits before moving to the next line. The parser returns an empty blockquote without consuming the line. Then it tries the same line again forever.
Any line that starts with
>and contains one of these characters triggers the bug. One exception:>\u2028xworks because\s?takes the character right after>.