From e4c42c011152c47ee9906ac3f6d4be5bdbed18be Mon Sep 17 00:00:00 2001 From: Maxim Date: Tue, 19 May 2026 17:34:48 +0300 Subject: [PATCH] Fix memory allocation in PSOperator and Type1FontProgram --- .../verapdf/parser/postscript/PSOperator.java | 21 ++++++++++++++----- .../pd/font/type1/Type1FontProgram.java | 10 ++++++++- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/verapdf/parser/postscript/PSOperator.java b/src/main/java/org/verapdf/parser/postscript/PSOperator.java index 2fbaf9c5..8e1f9c42 100644 --- a/src/main/java/org/verapdf/parser/postscript/PSOperator.java +++ b/src/main/java/org/verapdf/parser/postscript/PSOperator.java @@ -35,6 +35,8 @@ * @author Sergey Shemyakov */ public class PSOperator extends PSObject { + private static final int MAX_PS_ARRAY_SIZE = 1 << 16; + private static final int MAX_PS_FOR_ITERATIONS = 10_000; private Stack operandStack; private Map userDict; private final String operator; @@ -536,6 +538,9 @@ private void load() throws PostScriptException { private void array() throws PostScriptException { try { int arraySize = getTopNumber().getInteger().intValue(); + if (arraySize < 0 || arraySize > MAX_PS_ARRAY_SIZE) { + throw new PostScriptException("Array size " + arraySize + " is out of range"); + } COSObject array = COSArray.construct(arraySize); for (int i = 0; i < arraySize; i++) { array.add(COSObject.getEmpty()); @@ -577,11 +582,17 @@ private void opFor() throws PostScriptException { if (!(proc instanceof PSProcedure)) { throw new PostScriptException("Object is not a procedure"); } - COSObject limit = getTopNumber(); - COSObject increment = getTopNumber(); - COSObject initial = getTopNumber(); - for (long i = initial.getInteger(); i <= limit.getInteger(); - i += increment.getInteger()) { + long limit = getTopNumber().getInteger(); + long increment = getTopNumber().getInteger(); + long initial = getTopNumber().getInteger(); + if (increment == 0 || (increment > 0 && initial > limit) || (increment < 0 && initial < limit)) { + throw new PostScriptException("Wrong increment value " + increment); + } + long iterations = Math.abs((limit - initial) / increment) + 1; + if (iterations > MAX_PS_FOR_ITERATIONS) { + throw new PostScriptException("Loop iteration count " + iterations + " is too large"); + } + for (long i = initial; (increment > 0 ? i <= limit : i >= limit); i += increment) { operandStack.push(COSInteger.construct(i)); ((PSProcedure) proc).executeProcedure(operandStack, userDict); } diff --git a/src/main/java/org/verapdf/pd/font/type1/Type1FontProgram.java b/src/main/java/org/verapdf/pd/font/type1/Type1FontProgram.java index ea4e1e75..a3913282 100644 --- a/src/main/java/org/verapdf/pd/font/type1/Type1FontProgram.java +++ b/src/main/java/org/verapdf/pd/font/type1/Type1FontProgram.java @@ -54,6 +54,7 @@ public class Type1FontProgram extends PSParser implements FontProgram { public static final Logger LOGGER = Logger.getLogger(Type1FontProgram.class.getCanonicalName()); static final double[] DEFAULT_FONT_MATRIX = {0.001, 0, 0, 0.001, 0, 0}; + private static final int MAX_TO_EXECUTE_DEPTH = 64; private final COSKey key; @@ -187,12 +188,19 @@ private void processObject(COSObject nextObject) throws IOException, PostScriptE } private void toExecute(COSObject next) throws PostScriptException { + toExecute(next, 0); + } + + private void toExecute(COSObject next, int depth) throws PostScriptException { + if (depth > MAX_TO_EXECUTE_DEPTH) { + throw new PostScriptException("Type 1 font program exceeded toExecute recursion depth"); + } PSObject operator = PSObject.getPSObject(next); if (operator instanceof PSOperator) { if (!OPERATORS_KEYWORDS.contains(((PSOperator) operator).getOperator())) { COSObject dictEntry = userDict.get(ASAtom.getASAtom(((PSOperator) operator).getOperator())); if (dictEntry != null) { - toExecute(dictEntry); + toExecute(dictEntry, depth + 1); } } else { operator.execute(operandStack, userDict);