Author: tilman Date: Thu May 23 15:20:03 2024 New Revision: 1917926 URL: http://svn.apache.org/viewvc?rev=1917926&view=rev Log: PDFBOX-5827: avoid stack overflow by tracking the depth up to maxp.MaxComponentDepth
Modified: pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeDescript.java pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphData.java pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphTable.java Modified: pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeDescript.java URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeDescript.java?rev=1917926&r1=1917925&r2=1917926&view=diff ============================================================================== --- pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeDescript.java (original) +++ pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyfCompositeDescript.java Thu May 23 15:20:03 2024 @@ -56,9 +56,10 @@ public class GlyfCompositeDescript exten * * @param bais the stream to be read * @param glyphTable the Glyphtable containing all glyphs + * @param level current level * @throws IOException is thrown if something went wrong */ - GlyfCompositeDescript(TTFDataStream bais, GlyphTable glyphTable) throws IOException + GlyfCompositeDescript(TTFDataStream bais, GlyphTable glyphTable, int level) throws IOException { super((short) -1, bais); @@ -78,7 +79,7 @@ public class GlyfCompositeDescript exten { readInstructions(bais, (bais.readUnsignedShort())); } - initDescriptions(); + initDescriptions(level); } /** @@ -293,14 +294,14 @@ public class GlyfCompositeDescript exten return null; } - private void initDescriptions() + private void initDescriptions(int level) { for (GlyfCompositeComp component : components) { try { int index = component.getGlyphIndex(); - GlyphData glyph = glyphTable.getGlyph(index); + GlyphData glyph = glyphTable.getGlyph(index, level); if (glyph != null) { descriptions.put(index, glyph.getDescription()); Modified: pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphData.java URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphData.java?rev=1917926&r1=1917925&r2=1917926&view=diff ============================================================================== --- pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphData.java (original) +++ pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphData.java Thu May 23 15:20:03 2024 @@ -42,9 +42,11 @@ public class GlyphData * @param glyphTable The glyph table this glyph belongs to. * @param data The stream to read the data from. * @param leftSideBearing The left side bearing for this glyph. + * @param level composite level * @throws IOException If there is an error reading the data. */ - void initData( GlyphTable glyphTable, TTFDataStream data, int leftSideBearing ) throws IOException + void initData( GlyphTable glyphTable, TTFDataStream data, int leftSideBearing, int level) + throws IOException { numberOfContours = data.readSignedShort(); xMin = data.readSignedShort(); @@ -62,7 +64,7 @@ public class GlyphData else { // create a composite glyph - glyphDescription = new GlyfCompositeDescript(data, glyphTable); + glyphDescription = new GlyfCompositeDescript(data, glyphTable, level + 1); } } Modified: pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphTable.java URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphTable.java?rev=1917926&r1=1917925&r2=1917926&view=diff ============================================================================== --- pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphTable.java (original) +++ pdfbox/branches/2.0/fontbox/src/main/java/org/apache/fontbox/ttf/GlyphTable.java Thu May 23 15:20:03 2024 @@ -40,6 +40,7 @@ public class GlyphTable extends TTFTable private int cached = 0; private HorizontalMetricsTable hmt = null; + private MaximumProfileTable maxp = null; /** * Don't even bother to cache huge fonts. @@ -83,6 +84,8 @@ public class GlyphTable extends TTFTable // locks TrueTypeFont and then tries to lock "data" hmt = font.getHorizontalMetrics(); + maxp = ttf.getMaximumProfile(); + initialized = true; } @@ -139,7 +142,7 @@ public class GlyphTable extends TTFTable { ++cached; } - glyphs[gid] = getGlyphData(gid); + glyphs[gid] = getGlyphData(gid, 0); } initialized = true; return glyphs; @@ -162,6 +165,11 @@ public class GlyphTable extends TTFTable */ public GlyphData getGlyph(int gid) throws IOException { + return getGlyph(gid, 0); + } + + GlyphData getGlyph(int gid, int level) throws IOException + { if (gid < 0 || gid >= numGlyphs) { return null; @@ -196,7 +204,7 @@ public class GlyphTable extends TTFTable data.seek(getOffset() + offsets[gid]); - glyph = getGlyphData(gid); + glyph = getGlyphData(gid, level); // restore data.seek(currentPosition); @@ -212,11 +220,15 @@ public class GlyphTable extends TTFTable } } - private GlyphData getGlyphData(int gid) throws IOException + private GlyphData getGlyphData(int gid, int level) throws IOException { + if (level > maxp.getMaxComponentDepth()) + { + throw new IOException("composite glyph maximum level reached"); + } GlyphData glyph = new GlyphData(); int leftSideBearing = hmt == null ? 0 : hmt.getLeftSideBearing(gid); - glyph.initData(this, data, leftSideBearing); + glyph.initData(this, data, leftSideBearing, level); // resolve composite glyph if (glyph.getDescription().isComposite()) {