-
Notifications
You must be signed in to change notification settings - Fork 18
Fix memory allocation in PSOperator and Type1FontProgram #703
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: integration
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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<COSObject> operandStack; | ||||||||||||||||||||
| private Map<ASAtom, COSObject> 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); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
Comment on lines
+588
to
+590
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don’t throw on non-entering The direction-mismatch cases should be valid no-op loops, not Proposed fix- if (increment == 0 || (increment > 0 && initial > limit) || (increment < 0 && initial < limit)) {
+ if (increment == 0) {
throw new PostScriptException("Wrong increment value " + increment);
}
+ if ((increment > 0 && initial > limit) || (increment < 0 && initial < limit)) {
+ return;
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||
| 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); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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"); | ||||||||||||
|
Comment on lines
+195
to
+196
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix off-by-one in recursion depth guard.
Suggested patch- if (depth > MAX_TO_EXECUTE_DEPTH) {
+ if (depth >= MAX_TO_EXECUTE_DEPTH) {
throw new PostScriptException("Type 1 font program exceeded toExecute recursion depth");
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||
| } | ||||||||||||
| 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); | ||||||||||||
|
|
||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate array size before narrowing to
int.Line 540 narrows to
intbefore range validation, so oversized integers can wrap and evade the intended guard.Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents