发布

  • fix(frontend): cap deeply nested list indentation to prevent render crash (#3393) (#3570)

    frostbyte_neo 发布于 2026-06-14 14:19:54 +00:00 | 948 次提交 在此版本后已推送到 main

    • fix(frontend): cap deeply nested list indentation to prevent render crash

    Deeply nested lists make marked's recursive list tokenizer overflow the
    call stack during Streamdown's lexing useMemo, throwing an uncaught
    "RangeError: Maximum call stack size exceeded" that replaces the chat
    route with an error page (issue #3393); on larger stacks the same input
    exhausts the heap, which the render error boundary cannot catch.

    Mirror the existing capBlockquoteNesting guard with capListNesting, which
    clamps leading whitespace to 200 columns (~100 nesting levels) only when
    pathologically deep indentation is present, leaving normal content and
    fenced code untouched. Wire both through capMarkdownNesting.

    • fix(frontend): satisfy prettier format check in preprocess test

    • fix(frontend): exempt indented code from list-indent cap (PR #3570 review)

    • fix(frontend): keep capping all deep indentation outside fenced code

    Revert the indented-code exemption from the PR #3570 review nit. Taken
    literally the suggested guard (insideFence || INDENTED_CODE_RE.test(line))
    no-ops capListNesting, because INDENTED_CODE_RE matches every line with
    4+ leading spaces — i.e. exactly the deep-indent lines the cap targets.
    A context-aware exemption (only treat 4+-space lines as code after a
    blank line) instead reopens the crash: blank-separated deeply nested list
    items get exempted and still blow up marked (verified: OOM at depth ~1.5k).

    Unlike blockquotes (markers take <=3 leading spaces, so deep-quote lines
    never look like indented code), list vs. indented-code indentation is
    ambiguous line-by-line, so any exemption is exploitable. Keep capping all
    deep indentation outside fenced code; the only cost is mild corruption of
    a >200-column indented-code line, which never occurs in real content and
    is strictly preferable to a render crash. Add a regression test locking
    the blank-line case.

    下载附件