Skip to content

[v4] Infinite recursion (Maximum call stack size exceeded) triggered by \mathrel{-}= with preceding text #3573

Description

@Euler13

Issue Summary

MathJax v4 encounters an infinite recursion loop ("Maximum call stack size exceeded") that crashes the browser tab when parsing a forced relation containing a binary operator (\mathrel{-}) placed immediately adjacent to a native relational operator (=), provided it is not at the beginning of the math block.

This acts as a potential client-side DoS vulnerability, as a single malicious or malformed formula in a forum post will permanently crash the browser tab for anyone viewing the page.

Steps to Reproduce:

  1. Load MathJax v4 on a web page / Go to the official MathJax Live Demo page or load MathJax v4 on a web page.
  2. Attempt to render the following LaTeX string: $$h[mask] \mathrel{-}=$$
  3. Observe that the browser tab instantly freezes.
  4. Check the developer console to see the Maximum call stack size exceeded error.

Important Note on Reproduction: The preceding characters (like h[mask]) are strictly required to trigger the bug. If you parse \mathrel{-}= completely on its own, it renders safely. It appears that if the block is at the beginning of the line, the minus sign auto-downgrades from a BIN to an ORD, sidestepping the bug. If preceding characters exist, the - maintains its BIN status, triggering the infinite loop when negotiating spacing with the native = REL operator.

Expected Behavior:
Even if the LaTeX is considered poor practice (e.g., forcing a relation on a binary operator right next to another relation), the parser should either render it as written or throw a graceful parsing error. It should never enter an infinite loop that crashes the host browser.

Technical details:

  • MathJax Version: 4
  • Client OS: Windows 11
  • Browser: Firefox 151.0.4 or Chrome 149.0.7827.103

I am using the following MathJax configuration on my site (though again, this crashes the standard Live Demo as well):

window.MathJax = {
   startup: {
      pageReady: () => {
         for (const script of document.querySelectorAll('script[type^="math/tex"]')) {
            const math = document.createElement('span');
            math.innerText = script.text;
            script.parentNode.replaceChild(math, script);
         }
         return MathJax.startup.defaultPageReady().then(() => {
            document.querySelectorAll('a mjx-container').forEach(container => {
               container.addEventListener('mousedown', (event) => {
                  const link = container.closest('a');
                  if (link && event.button === 0 && !event.ctrlKey && !event.metaKey) {
                     window.location.href = link.href;
                  }
               });
            });
         });
      }
   },
   tex: {
      inlineMath: [ ['$','$'] ],
      displayMath: [ ['$$','$$'] ],
      processEscapes: true,
      processEnvironments: false
   },
   options: {
      ignoreHtmlClass: 'text-block'
   }
};

and loading MathJax via

<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-mml-svg.js?config=newcm"></script>

Supporting information:

Live Example: Can be reproduced directly on the MathJax Live Demo site by pasting $$h[mask] \mathrel{-}=$$.

Console Error: The console explicitly reports Uncaught RangeError: Maximum call stack size exceeded.

Suspected Mechanism: The crash appears to happen during the AST spacing traversal (likely inside setTeXclass or similar). The generated by \mathrel claims to be a REL class, but the inner node - is a BIN class. When the native = sign (a REL) asks its neighbor for its spacing class, it seems to trigger an infinite ping-pong evaluation between the parent wrapper's forced class and the child node's native class.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions