Skip to content

Make the markdown/frontmatter regexes linear (CodeQL polynomial-redos) - #89

Merged
kriswill merged 2 commits into
mainfrom
fix/polynomial-redos
Oct 23, 2026
Merged

kriswill merged 2 commits into
mainfrom
fix/polynomial-redos

Conversation

@kriswill

@kriswill kriswill commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

Resolves all ten open code scanning alerts (js/polynomial-redos, lib.ts and migrate-doc.ts) from CodeQL's first scan of the repo.

What changed

Each flagged regex had two adjacent repetitions that could match the same text (\s+ next to .*, .*\S next to \s*$, a lazy ^(.*?) ahead of a bracket class), so a crafted line made it backtrack quadratically. Each is rewritten so the repetitions cannot overlap, or replaced by a loop or an indexed search:

Site Before After
lenientScalars (\s+)?)(.*)$ value starts at its first non-space: (\S.*)?$
FOOTNOTE_DEF_RE :\s*(.*)$ :(.*), callers already trim
list items (citations, migrate) \s+(.*\S)\s*$ twice one shared listItemText(): \s+(\S.*) + trimEnd
citation link ^(.*?)\[([^\]]*)\]\(… unanchored search, prefix by index; no part of a candidate crosses [
separator trim /[\s:—–-]+$/ a loop
sourceId ^-+|-+$ dashes are already collapsed: ^-|-$
linkFieldValues \[\[(.*?)(?:|.*)?\]\] `[[([^
firstHeading ^#\s+(.+?)\s*$ ^#\s+(\S.*) + trimEnd

Verification

  • Old and new regexes were run side by side over every line of every .md/.ts/.toml file in the repo (183k lines, 1.1M comparisons): no differences on real content.
  • The pumps CodeQL named, at 200k characters each, went from 5–10 s to under 1 ms. A new test pins that.
  • 617 tests pass, tsgo --noEmit clean.

Deliberate edge-case changes

  • A # heading with no text no longer yields a single-space title; the search moves on to the next heading.
  • A CRLF footnote definition ([^a]: text\r) now parses; before, $ rejected it.
  • [a [b](u) yields link text b with prefix [a (CommonMark's reading), not a [b.

Summary by CodeRabbit

  • Bug Fixes
    • Improved citation recognition in Markdown list items, including citations containing links or bare URLs.
    • Improved handling of source identifiers, link fields, headings, and frontmatter values with whitespace or special characters.
    • Updated citation migration to recognize list-item formatting more consistently.
  • Performance
    • Added coverage for large Markdown and frontmatter inputs to help ensure parsing remains responsive.

…dos)

CodeQL's first scan of the repo flagged ten regexes whose whitespace or
wildcard runs overlap, so a crafted line makes them backtrack quadratically.
Each is rewritten so no two adjacent repetitions can match the same text, or
replaced by a loop or an indexed search:

- lenientScalars: the value starts at its first non-space.
- FOOTNOTE_DEF_RE: `:(.*)` without `\s*` or `$`; callers already trim.
- list items (citations, migrate): one `listItemText()` helper, `\s+(\S.*)`
  plus trimEnd, shared so both sides agree.
- citation links: unanchored search with the prefix taken by index instead
  of a lazy `^(.*?)`; no part of a candidate crosses a `[`, so the scan is
  linear even on bracket-heavy items.
- separator trim before a link: a loop instead of `/[...]+$/`.
- sourceId: dashes are already collapsed, so `^-|-$`.
- linkFieldValues: the wikilink target is `[^|]*`.
- firstHeading: `\s+(\S.*)` plus trimEnd.

Behavior is unchanged on every line of every file in the repo (checked
differentially). Three deliberate edge-case changes: a `#` heading with no
text no longer yields a whitespace title; a CRLF footnote definition now
parses; `[a [b](u)` yields the link text `b` (CommonMark), not `a [b`.

Adds a regression test with the pumps CodeQL named, 200k chars each.
@coderabbitai

coderabbitai Bot commented Oct 23, 2026

Copy link
Copy Markdown

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 8d92b771-b8e2-4c3c-85a8-0204770f12df
📥 Commits

Reviewing files that changed from the base of the PR and between a0ea296 and 308fce9.

📒 Files selected for processing: 4
  • lib.ts
  • migrate-doc.ts
  • test/lib.test.ts
  • viz-app/okf-fields.ts
+------------------------------------------------------------------------------------------+
| Recursion is the root of computation since it trades description for time. - Alan Perlis |
+------------------------------------------------------------------------------------------+
  \
   \     /)/)
        ( '')
        /  |
      o(___)
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The Windows CI job (added in #82) fails on main in vcs.test.ts: at a fresh
git toplevel under tmpdir(), "auto" degraded to the filesystem provider.
git prints the toplevel as C:/Users/runneradmin/... while tmpdir() is the
8.3-spelled C:\Users\RUNNER~1\..., and realpathSync does not reconcile
them. `git rev-parse --show-prefix` is empty exactly at the toplevel, so
use that and drop the path comparison.
@kriswill
kriswill merged commit 9d137f5 into main Oct 23, 2026
7 checks passed
@kriswill
kriswill deleted the fix/polynomial-redos branch October 23, 2026 18:02
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.

1 participant