fix(shared): bound the file-link label so bracket runs stop rescanning - #5782
Conversation
FILE_LINK_TOKEN_REGEX let the label body repeat without a bound. Every whitespace in the composer is therefore a candidate start: the engine scans the rest of the text for a closing "]", fails, and rescans from the next whitespace. On a run of unterminated brackets that is quadratic, and collectComposerInlineTokens runs on raw composer text, so pasting one freezes the tab. Capping the body makes each attempt constant-bounded: 120k chars of " [[" 2838ms -> 33ms 60k chars 676ms -> 17ms 30k chars 167ms -> 8ms The cap cannot reject a link anyone could meaningfully write. Only a basename survives the `label !== basename` check below it, and the longest filename common filesystems allow is 255. Verified equivalent to the old pattern over 156,504 generated inputs built from [ ] ( ) \ @ " whitespace and path-ish fragments, comparing match count, offsets and every capture group: zero differences. The single intended difference is at the cap itself, which the two new boundary tests pin. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Approved 9b71e34 This is a straightforward performance bug fix that bounds a regex to prevent quadratic backtracking on pathological input. The 512-character limit is generous (max filename is 255) and includes comprehensive tests verifying the boundary behavior. You can customize Macroscope's approvability policy. Learn more. |
## What's Changed * fix(server): favicon resolution no longer pins the event loop by @murenovich in pingdotgg/t3code#5538 * fix(shared): bound the file-link label so bracket runs stop rescanning by @tsouth89 in pingdotgg/t3code#5782 ## New Contributors * @murenovich made their first contribution in pingdotgg/t3code#5538 * @tsouth89 made their first contribution in pingdotgg/t3code#5782 **Full Changelog**: pingdotgg/t3code@v0.0.33-nightly.20260809.1045...v0.0.33-nightly.20260809.1047 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.33-nightly.20260809.1047
fix(shared): bound the file-link label so bracket runs stop rescanning
What changed
FILE_LINK_TOKEN_REGEXinpackages/shared/src/composerInlineTokens.tslet thelabel body repeat without a bound:
/(^|\s)\[((?:\\.|[^\]\\])*)\]\(([^)\s]+)\)(?=\s)/gThis caps it at 512 characters. Two files, +36/-1.
Why it should exist
With an unbounded body, every whitespace in the composer is a candidate start:
the engine scans the rest of the text for a closing
], fails, then rescansfrom the next whitespace. On a run of unterminated brackets that is quadratic,
and
collectComposerInlineTokensruns on raw composer text — so pasting onefreezes the tab.
Measured on
" [["repeated, before → after:Doubling the input quadruples the old time, which is the quadratic signature.
Scope, stated honestly: ordinary pastes are unaffected, because a
]anywhereahead bounds each attempt. A 104k-char markdown table of
[a] [b] [c]cells anda 172k-char code paste full of
arr[i][j][k]both measure 0ms before and after.The trigger is a long run of
[with no closing bracket following. So this is aself-inflicted UI freeze on degenerate or hostile paste content, not a server-side
availability issue — worth fixing, not worth alarm.
Why the cap is safe
The cap cannot reject a link anyone could meaningfully write. Only a basename
survives the
label !== basenamecheck immediately below the match, and thelongest filename any common filesystem allows is 255.
How it was verified
Behavioural equivalence against the old pattern over 156,504 generated
inputs — exhaustive triples over an alphabet of
[ ] ( ) \ @ ", tab, newline,space and path-ish fragments; structured
[label](path)shapes across prefix andsuffix contexts; and 150,000 randomized fuzz strings. Compared match count, match
offsets, and every capture group.
Zero differences.
The single intended difference is at the cap itself: a 512-character label still
matches, 513 no longer does. The two new boundary tests pin exactly that, and a
third asserts the bracket-run case completes in under a second.
No UI change, so no screenshots — this is pure tokenizer logic behind the
composer.
Note
Low Risk
Localized tokenizer regex change with extensive equivalence testing; only rejects implausibly long link labels and improves client-side paste performance.
Overview
Fixes composer freezes when pasted text has long runs of unclosed
[brackets by capping how much of a[label](path)label the file-link regex will scan.FILE_LINK_TOKEN_REGEXincomposerInlineTokens.tsno longer uses an unbounded label repeat; it limits the label body to 512 characters viaMAX_FILE_LINK_LABEL_LENGTH, so each match attempt is constant-bounded instead of rescanning the rest of the string from every whitespace (quadratic on inputs like repeated" [[").Normal file links are unchanged in practice because only basenames pass validation and real filenames are far below the cap. Links with labels at 512 chars still tokenize; longer labels are left as plain text.
Tests add cap boundary cases and a performance guard on a 40k-char unterminated bracket run.
Reviewed by Cursor Bugbot for commit 9b71e34. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Bound file-link label length to 512 chars to prevent catastrophic bracket rescanning
MAX_FILE_LINK_LABEL_LENGTH = 512in composerInlineTokens.ts and rebuildsFILE_LINK_TOKEN_REGEXwith a bounded quantifier to cap label body length.Macroscope summarized 9b71e34.