medium

CVE-2026-53531

crates.io · ratex-parser

Summary

ratex-parser has unbounded parser recursion that leads to stack overflow (process abort)

Severity
medium
EPSS
0.3% (p24)
CWE
CWE-400, CWE-674
Also known as
GHSA-4w5h-hx6r-28q7
Published
2026-07-07
Updated
2026-07-07

Advisory details

Summary

RaTeX’s recursive-descent parser recurses one (or more) native stack frame per nesting level at {, \left, \sqrt{, ^{, etc, with no maximum depth limit. A short, ~10 KB input of nested groups overflows the 8 MB main-thread stack and aborts the process. With panic = "abort" (Cargo.toml:48), and because a Rust stack overflow is always a fatal SIGABRT regardless of panic strategy this is an unrecoverable, whole-process denial of service reachable from a single untrusted LaTeX string.

Details

The mutual recursion has no depth guard (crates/ratex-parser/src/parser.rs):

parse_expression (:113)  ->  parse_atom (:281/285)  ->  parse_group (:451)
                                  ^                          |
                                  |   on '{' (:459) recurse  |
                                  +--------------------------+

\left adds another recursive edge: handle_leftparse_expression (crates/ratex-parser/src/functions/left_right.rs:47). The only counters present are unrelated to depth: leftright_depth (a \right-matching counter, parser.rs:24) and the macro expander’s max_expand = 1000 (macro_expander.rs:64), which does not gate brace / \left recursion (those tokens never pass through expand_once). There is no recursion_limit/depth parameter on parse_group, parse_expression, or parse_atom.

PoC

image
$ python3 -c 'import sys;sys.stdout.write("{"*200000+"x"+"}"*200000)' | ./target/release/parse
thread 'main' has overflowed its stack
fatal runtime error: stack overflow, aborting
Aborted (core dumped)            # exit 134

(Other nesting forms work equally, e.g. \left(×N, \sqrt{×N, ^{×N.)

Impact

A single small request crashes the whole RaTeX process. In a typical server-side math-rendering service this is a reliable, unauthenticated DoS; on smaller worker-thread stacks (e.g. a 512 KB async runtime thread) only a few hundred bytes of nesting are required.

References

Related advisories

Is your project exposed to this? Stateward checks every dependency on every pull request and flags it only if your code actually reaches it.

Check my repo

Summarize with AI

ChatGPTClaudePerplexity

Sources: CISA KEV (public domain), OSV.dev & GitHub Advisory Database (CC-BY-4.0), FIRST EPSS, NVD/CWE (public domain). Served live from the Stateward advisory database.