diff --git a/src/core/font_renderer.js b/src/core/font_renderer.js index b7528f080..29d0f0818 100644 --- a/src/core/font_renderer.js +++ b/src/core/font_renderer.js @@ -168,7 +168,13 @@ function lookupCmap(ranges, unicode) { }; } -function compileGlyf(code, cmds, font) { +function compileGlyf(code, cmds, font, visitedGlyphs = new Set()) { + if (visitedGlyphs.has(code)) { + warn("compileGlyf: skipping recursive composite glyph reference."); + return; + } + + visitedGlyphs.add(code); function moveTo(x, y) { if (firstPoint) { // Close the current subpath in adding a straight line to the first point. @@ -250,7 +256,7 @@ function compileGlyf(code, cmds, font) { // TODO: we must use arg1 and arg2 to make something similar to: // https://github.com/freetype/freetype/blob/edd4fedc5427cf1cf1f4b045e53ff91eb282e9d4/src/truetype/ttgload.c#L1209 } - compileGlyf(subglyph, cmds, font); + compileGlyf(subglyph, cmds, font, visitedGlyphs); cmds.restore(); } } while (flags & 0x20); @@ -352,6 +358,7 @@ function compileGlyf(code, cmds, font) { startPoint = endPoint + 1; } } + visitedGlyphs.delete(code); } function compileCharString(charStringCode, cmds, font, glyphId) { diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 65edc5dc8..7d83280fe 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -899,3 +899,4 @@ !issue16091.pdf !issue7821.pdf !issue21068.pdf +!recursiveCompositGlyf.pdf diff --git a/test/pdfs/recursiveCompositGlyf.pdf b/test/pdfs/recursiveCompositGlyf.pdf new file mode 100644 index 000000000..dd8817238 Binary files /dev/null and b/test/pdfs/recursiveCompositGlyf.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index d7d1cf08c..992ad54aa 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -14105,5 +14105,12 @@ "link": true, "rounds": 1, "type": "eq" + }, + { + "id": "recursiveCompositGlyf", + "file": "pdfs/recursiveCompositGlyf.pdf", + "md5": "e4e106d20e4af10d7a5f1a5da02db66f", + "rounds": 1, + "type": "eq" } ]