CVE-2026-53530: ratex-parser Process Abort via UTF-8 Multibyte Delimiter in \verb
Sending a nine-byte LaTeX string with a non-ASCII delimiter to ratex-parser causes the Rust process to abort immediately, taking down any server or pipeline that renders untrusted LaTeX.
The problem
The parse_symbol_inner function in crates/ratex-parser/src/parser.rs handles \verb by slicing its argument with raw byte indices (arg[1..arg.len() - 1]). When the delimiter character is a multibyte UTF-8 sequence, byte index 1 falls inside that character and Rust panics.
Because the release profile sets panic = "abort" in Cargo.toml, the panic does not unwind or stay contained to a thread. It aborts the entire process, so one malicious formula is enough to cause a full-service denial of service in any web endpoint, WASM renderer, or FFI-embedded build.
Proof of concept
A working proof-of-concept for CVE-2026-53530 in ratex-parser, with the exact payload below.
$ printf '\\verb\xc3\xa9x\xc3\xa9\n' | ./target/release/parse
thread 'main' panicked at crates/ratex-parser/src/parser.rs:910:27:
start byte index 1 is not a char boundary; it is inside 'é' (bytes 0..2 of string)
Aborted (core dumped)The input \verbéxé strips the \verb prefix, leaving arg = "éxé". The character é (U+00E9) encodes as two bytes (0xC3 0xA9), so arg.len() is 5. The byte-length guard arg.len() < 2 passes, and arg[1..4] attempts a slice starting at byte 1, which is the interior of a two-byte sequence.
Rust enforces UTF-8 char boundaries on string slices and panics unconditionally here.
The lexer (lexer.rs, lex_verb) already tokenises the verb argument correctly using char-aware iteration. Only the parser then re-slices the already-tokenised string with byte offsets, which is the isolated root cause (CWE-129, improper index validation; CWE-248, uncaught exception; CWE-400, uncontrolled resource consumption via abort).
The fix replaces byte slicing with char-collection: let chars: Vec<char> = arg.chars().collect(), guards on chars.len() < 2, and reconstructs the body as chars[1..chars.len()-1].iter().collect::<String>(). The same char-aware strip replaces the *-prefix byte slice at line 905.
The fix
Upgrade ratex-parser to **0.1.11**. The patch rewrites the \verb body extraction in parse_symbol_inner to use character indices instead of byte indices, matching the UTF-8-correct approach already used in the lexer. If you embed RaTeX in a long-running service before you can upgrade, wrap the call site in std::panic::catch_unwind as a short-term mitigation, and consider whether panic = "abort" is appropriate for your deployment profile.
Related research
- high · 7.5CVE-2026-16756CVE-2026-16756: aws-smithy-http-server Slowloris Denial of Service
- high · 7.5CVE-2026-25800: quinn-proto Unbounded Stream Reassembly Memory Exhaustion
- criticalexploration: Malicious Remote Code Execution via Embedded Downloader
- high · 7.1CVE-2026-35341CVE-2026-35341: uu_mkfifo Unauthorized Permission Overwrite on Existing Files