Skip to content

Stop morx state machines that never advance (#175) - #428

Closed
iliev-blnk wants to merge 1 commit into
foliojs:masterfrom
iliev-blnk:morx-dont-advance-limit
Closed

iliev-blnk wants to merge 1 commit into
foliojs:masterfrom
iliev-blnk:morx-dont-advance-limit

Conversation

@iliev-blnk

Copy link
Copy Markdown
Contributor

Fixes #175

Cause

AATStateMachine.process advances only when an entry has no DontAdvance flag. A font whose transitions all carry DontAdvance keeps the machine on the same glyph forever, so font.layout() never returns. Test case MORX-24 does this with a contextual subtable that substitutes A → B → C → D → E → A.

Fix

Like HarfBuzz, each glyph run gets a budget of max(4096 * glyphs, 65536) steps, the same values as HB_BUFFER_MAX_OPS_FACTOR and HB_BUFFER_MAX_OPS_MIN. A transition that doesn't advance uses up one step. Once the budget runs out, the machine advances anyway. The budget is shared by all subtables in the run. Fonts that use DontAdvance as intended spend only a few steps of it.

The cost is still proportional to the budget: 5 glyphs of MORX-24 now finish in about 20 ms, and 10,000 glyphs take a few seconds instead of hanging.

Tests

  • test/issues.js: MORX-24 lays out ABCDE and returns 5 glyphs. On master, the test hangs.
  • The test font is TestMORXTwentyfour.ttf from Unicode text-rendering-tests, added to test/data/fonttest/ next to the other fonts from there, under the Apache License 2.0 in test/data/fonttest/LICENSE.txt.
  • npm test: 704 passing. npm run format:check passes.

Transitions with DontAdvance now use up a budget of max(4096 * glyphs,
65536) steps per glyph run, as in HarfBuzz. Once it runs out, the
machine advances anyway, so a font that cycles through substitutions
without advancing no longer hangs layout.

The test font is TestMORXTwentyfour.ttf (MORX-24) from Unicode
text-rendering-tests, under the Apache License 2.0 in
test/data/fonttest/LICENSE.txt.
@blikblum

Copy link
Copy Markdown
Member

Sorry. I merged other PR first

@iliev-blnk

Copy link
Copy Markdown
Contributor Author

No problem — #429 included this commit, so the fix for #175 is already on master. Closing this one.

@iliev-blnk iliev-blnk closed this Oct 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[morx] Infinite loop for test case MORX-24

2 participants