Skip to content

Commit

Permalink
fix: maxExpand limit with Unicode sub/superscripts
Browse files Browse the repository at this point in the history
* Prevent recursive parser calls from over-expansion

* Use this.subparse instead of a recursive parser.

* Add maxExpand tests

* Lint fix

---------

Co-authored-by: Ron Kok <ronkok55@outlook.com>
  • Loading branch information
edemaine and ronkok committed Mar 24, 2024
1 parent e88b4c3 commit 085e21b
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
7 changes: 4 additions & 3 deletions src/Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,19 +405,20 @@ export default class Parser {
// We treat these similarly to the unicode-math package.
// So we render a string of Unicode (sub|super)scripts the
// same as a (sub|super)script of regular characters.
let str = uSubsAndSups[lex.text];
const isSub = unicodeSubRegEx.test(lex.text);
const subsupTokens = [];
subsupTokens.push(new Token(uSubsAndSups[lex.text]));
this.consume();
// Continue fetching tokens to fill out the string.
while (true) {
const token = this.fetch().text;
if (!(uSubsAndSups[token])) { break; }
if (unicodeSubRegEx.test(token) !== isSub) { break; }
subsupTokens.unshift(new Token(uSubsAndSups[token]));
this.consume();
str += uSubsAndSups[token];
}
// Now create a (sub|super)script.
const body = (new Parser(str, this.settings)).parse();
const body = this.subparse(subsupTokens);
if (isSub) {
subscript = {type: "ordgroup", mode: "math", body};
} else {
Expand Down
23 changes: 23 additions & 0 deletions test/katex-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4002,6 +4002,29 @@ describe("The maxExpand setting", () => {
expect`\edef0{x}\edef0{00}\edef0{00}\edef0{00}\edef0{00}`.not.toParse(
new Settings({maxExpand: 10}));
});
const exp32 = r`
\def\a#1{\b{#1}\b{#1}}
\def\b#1{\c{#1}\c{#1}}
\def\c#1{\d{#1}\d{#1}}
\def\d#1{\e{#1}\e{#1}}
\def\e#1{\f{#1}\f{#1}}
\def\f#1{#1}
`;
it("should count correctly", () => {
const example = exp32 + r`\a{1}`;
const count = 1 + 2 + 4 + 8 + 16 + 32;
expect(example).toParse(new Settings({maxExpand: count}));
expect(example).not.toParse(new Settings({maxExpand: count - 1}));
});
it("should count correctly with Unicode sub/superscripts", () => {
const example = exp32 + r`\def+{\a{1}}x⁺x⁺x⁺x⁺`;
const count = (1 + 2 + 4 + 8 + 16 + 32) * 4 + 4;
expect(example).toParse(new Settings({maxExpand: count}));
expect(example).not.toParse(new Settings({maxExpand: count - 1}));
});
});
describe("The \\mathchoice function", function() {
Expand Down

0 comments on commit 085e21b

Please sign in to comment.