Summary
Description
A PostScript-interpreter-driven Denial of Service (CWE-1325) vulnerability in veraPDF allows a remote attacker to exhaust validator memory or CPU by submitting a PDF whose Type 1 font /FontFile is a font program containing attacker-supplied PostScript. veraPDF's Type 1 font program parser dispatches every cleartext token through a hardcoded operator allow-list whose members include the unbounded array N allocation operator and the for control operator with no zero-increment guard. This affects all current versions of veraPDF-parser.
Details
The vulnerability resides in veraPDF-parser. Type 1 font program streams referenced from any Type 1 font's /FontDescriptor /FontFile are parsed by Type1FontProgram (veraPDF-parser/src/main/java/org/verapdf/pd/font/type1/Type1FontProgram.java), which extends PSParser. parseFont reads cleartext PostScript tokens until it encounters eexec (which switches into the encrypted private dictionary parser) or end-of-stream. Each non-eexec token is dispatched via toExecute, which gates execution behind a hardcoded allow-list.
The allow-list explicitly admits both ARRAY (Type1FontProgram.java:98) and FOR (Type1FontProgram.java:100). When either keyword passes the gate, operator.execute delegates straight into the generic PSOperator implementation (org.verapdf.parser.postscript.PSOperator, methods array() at PSOperator.java:536-547 and opFor() at PSOperator.java:571-592), which apply no validation:
array N calls COSArray.construct(N) followed by new ArrayList<>(N) (COSArray.java:102), so the underlying Object[] is allocated up-front. Passing 2147483647 (Integer.MAX_VALUE) requests a 16 GB backing array on a 64-bit JVM.
for runs for (long i = initial; i <= limit; i += increment) with no validation of increment. With increment == 0, the loop never exits.
In addition to the two shared primitives, toExecute introduces a third primitive specific to this code path: when an unknown operator is encountered, it looks the name up in userDict and recursively re-executes the value. There is no visited-set, no recursion-depth cap, and no detection of a cycle. A Type 1 font program that defines a name to itself, such as /loop { loop } def loop, recurses indefinitely on the JVM stack and throws StackOverflowError after ~16,000 frames.
The interpreter is reachable on every Type 1 font validation. GFPDType1Font's constructor unconditionally calls program.parseFont().
Type1FontProgram.parseFont only catches PostScriptException and rewraps it as IOException; it does not catch OutOfMemoryError, StackOverflowError, or wall-clock budget, so any of the three failure modes propagates out of font model construction and aborts the validation worker.
A single payload byte sequence is sufficient. The conventional %!PS-AdobeFont-1.0 header line is treated as a comment and skipped; the parser then begins consuming PostScript tokens, the very first for invocation enters the infinite loop, and the parser never reaches the eexec boundary that would normally end the cleartext section.
Impact
This impacts all current releases of the veraPDF-parser. Successful exploitation requires only that the target validate an attacker-supplied PDF; a single Type 1 font with a malicious /FontFile stream is sufficient.
References
Summary
Description
A PostScript-interpreter-driven Denial of Service (CWE-1325) vulnerability in veraPDF allows a remote attacker to exhaust validator memory or CPU by submitting a PDF whose Type 1 font
/FontFileis a font program containing attacker-supplied PostScript. veraPDF's Type 1 font program parser dispatches every cleartext token through a hardcoded operator allow-list whose members include the unboundedarray Nallocation operator and theforcontrol operator with no zero-increment guard. This affects all current versions of veraPDF-parser.Details
The vulnerability resides in veraPDF-parser. Type 1 font program streams referenced from any Type 1 font's
/FontDescriptor /FontFileare parsed byType1FontProgram(veraPDF-parser/src/main/java/org/verapdf/pd/font/type1/Type1FontProgram.java), which extendsPSParser.parseFontreads cleartext PostScript tokens until it encounterseexec(which switches into the encrypted private dictionary parser) or end-of-stream. Each non-eexectoken is dispatched viatoExecute, which gates execution behind a hardcoded allow-list.The allow-list explicitly admits both
ARRAY(Type1FontProgram.java:98) andFOR(Type1FontProgram.java:100). When either keyword passes the gate,operator.executedelegates straight into the genericPSOperatorimplementation (org.verapdf.parser.postscript.PSOperator, methodsarray()at PSOperator.java:536-547 andopFor()at PSOperator.java:571-592), which apply no validation:array NcallsCOSArray.construct(N)followed bynew ArrayList<>(N)(COSArray.java:102), so the underlyingObject[]is allocated up-front. Passing2147483647(Integer.MAX_VALUE) requests a 16 GB backing array on a 64-bit JVM.forrunsfor (long i = initial; i <= limit; i += increment)with no validation ofincrement. Withincrement == 0, the loop never exits.In addition to the two shared primitives,
toExecuteintroduces a third primitive specific to this code path: when an unknown operator is encountered, it looks the name up inuserDictand recursively re-executes the value. There is no visited-set, no recursion-depth cap, and no detection of a cycle. A Type 1 font program that defines a name to itself, such as/loop { loop } def loop, recurses indefinitely on the JVM stack and throwsStackOverflowErrorafter ~16,000 frames.The interpreter is reachable on every Type 1 font validation.
GFPDType1Font's constructor unconditionally callsprogram.parseFont().Type1FontProgram.parseFontonly catchesPostScriptExceptionand rewraps it asIOException; it does not catchOutOfMemoryError,StackOverflowError, or wall-clock budget, so any of the three failure modes propagates out of font model construction and aborts the validation worker.A single payload byte sequence is sufficient. The conventional
%!PS-AdobeFont-1.0header line is treated as a comment and skipped; the parser then begins consuming PostScript tokens, the very firstforinvocation enters the infinite loop, and the parser never reaches theeexecboundary that would normally end the cleartext section.Impact
This impacts all current releases of the veraPDF-parser. Successful exploitation requires only that the target validate an attacker-supplied PDF; a single Type 1 font with a malicious
/FontFilestream is sufficient.References