[
https://issues.apache.org/jira/browse/PDFBOX-6297?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
netwind updated PDFBOX-6297:
----------------------------
Attachment: Cmap12Poc.java
run-poc.bat
poc-cmap13-1k.ttf
poc-cmap13-100k.ttf
run-output.txt
> cmap format 12/13: nbGroups is unbounded, a 1.2 MB font takes 41 minutes to
> parse
> ---------------------------------------------------------------------------------
>
> Key: PDFBOX-6297
> URL: https://issues.apache.org/jira/browse/PDFBOX-6297
> Project: PDFBox
> Issue Type: Bug
> Components: FontBox
> Affects Versions: 3.0.9 PDFBox
> Environment: FontBox 3.0.8, JDK 21.0.11, Windows 11
> Reporter: netwind
> Priority: Major
> Attachments: Cmap12Poc.java, poc-cmap13-100k.ttf, poc-cmap13-1k.ttf,
> run-output.txt, run-poc.bat
>
>
> FontBox 3.0.8, Java 21.0.11, Windows 11. The trunk code of CmapSubtable is
> the same except for the logging calls.
> processSubtype12 and processSubtype13 read nbGroups as a 32-bit value and
> never check it. processSubtype8 in the same file caps the same field at
> 65536, with the comment "nbGroups shouldn't be greater than 65536".
> For format 13 the inner loop runs once per character code of every group, so
> a group of (0, 0x10FFFF, 0) is 12 bytes that become 1,114,112 map puts, and
> the outer loop repeats that until the data ends. With a minimal but valid TTF
> (nine tables, maxp claims 2 glyphs, one format 13 subtable, 100,000 groups,
> 1.2 MB) TTFParser.parseEmbedded takes 41 minutes on one core. The parse
> succeeds, no warnings, memory stays around 100 MB - it is just slow. 1,000
> groups (12 KB) already take 25 seconds.
> Format 12 is affected as well, but its inner loop stops at the first glyph
> index at or above numGlyphs, so a group is capped at numGlyphs puts; 10,000
> groups (131 KB, numGlyphs=65535) take 16 seconds.
> Expected: a font this small parses in a second or two. Actual: one core
> pinned for minutes.
> Both sample fonts and the generator are attached. "run-poc.bat 13 100000"
> reproduces the 41 minute case. Suggested fix: give format 12 and 13 the same
> 65536 cap format 8 has, or compare nbGroups against the bytes left in the
> table.
> {code:java}
> // CmapSubtable.java, line 300 (13) and 243 (12) in 3.0.8
> long nbGroups = data.readUnsignedInt(); // no upper bound
> ...
> for (long j = 0; j <= endCode - firstCode; ++j) { // up to 0x110000 puts per
> group
> characterCodeToGlyphId.put((int) (firstCode + j), (int) glyphId);
> }
> {code}
> One more thing in the same function: processSubtype13 checks "glyphId >
> numGlyphs" and then indexes glyphIdToCharacterCode[glyphId], so glyphId ==
> numGlyphs passes the check and throws AIOOBE instead of the intended warning.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]