Skip to content

Commit

Permalink
close #165: StackOverflowError in PDPageTree.getInheritableAttribute
Browse files Browse the repository at this point in the history
  • Loading branch information
ediweissmann committed Oct 18, 2023
1 parent dc88e8b commit 5821e48
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 4 deletions.
16 changes: 15 additions & 1 deletion src/main/java/org/sejda/sambox/pdmodel/PDPageTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.sejda.sambox.cos.COSName;
import org.sejda.sambox.cos.COSNull;
import org.sejda.sambox.cos.COSObjectable;
import org.sejda.sambox.util.ObjectIdUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -136,6 +137,11 @@ public static <T extends COSBase> COSBase getInheritableAttribute(COSDictionary
* @return COS value for the given key
*/
public static COSBase getInheritableAttribute(COSDictionary node, COSName key)
{
return getInheritableAttribute(node, key, new HashSet<>());
}

public static COSBase getInheritableAttribute(COSDictionary node, COSName key, Set<String> visitedObjectIds)
{
COSBase value = node.getDictionaryObject(key);
if (value != null)
Expand All @@ -154,7 +160,15 @@ public static COSBase getInheritableAttribute(COSDictionary node, COSName key)

if (parent != null)
{
return getInheritableAttribute(parent, key);
String objId = ObjectIdUtils.getObjectIdOf(node);
if(!objId.isBlank() && visitedObjectIds.contains(objId))
{
// prevent infinite recursion
return null;
}

visitedObjectIds.add(objId);
return getInheritableAttribute(parent, key, visitedObjectIds);
}

return null;
Expand Down
42 changes: 42 additions & 0 deletions src/main/java/org/sejda/sambox/util/ObjectIdUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sejda.sambox.util;

import org.sejda.sambox.cos.COSObjectKey;
import org.sejda.sambox.cos.COSObjectable;

public class ObjectIdUtils {
private ObjectIdUtils() {}

public static String getObjectIdOf(COSObjectable obj)
{
try
{
return getObjectIdOf(obj.getCOSObject().id().objectIdentifier);
}
catch (Exception ex)
{
return "";
}
}

public static String getObjectIdOf(COSObjectKey ident)
{
String gen = ident.generation() == 0 ? "" : ident.generation() + "";
return ident.objectNumber() + "R" + gen;
}
}
39 changes: 36 additions & 3 deletions src/test/java/org/sejda/sambox/pdmodel/PDPageTreeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.endsWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.junit.Assert.*;
import static org.sejda.sambox.input.PDFParser.parse;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

import org.junit.Test;
import org.sejda.io.SeekableSources;
import org.sejda.sambox.cos.COSBase;
import org.sejda.sambox.cos.COSDictionary;
import org.sejda.sambox.cos.COSName;
import org.sejda.sambox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
import org.sejda.sambox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
Expand Down Expand Up @@ -336,4 +337,36 @@ public void noStackOverflowInCaseOfLoop() throws IOException
doc.getPage(0);
}
}

@Test
public void getInheritableAttribute_recursive() throws IOException {
PDDocument doc = new PDDocument();
PDPage page = new PDPage();

doc.addPage(page);

COSDictionary dic1 = page.getCOSObject();
COSDictionary dic2 = new COSDictionary();
COSDictionary dic3 = new COSDictionary();

dic1.setItem(COSName.PARENT, dic2);
dic2.setItem(COSName.PARENT, dic3);
dic3.setItem(COSName.PARENT, dic1);

File tempFile = Files.createTempFile("sambox_getInheritableAttribute_recursive", ".pdf").toFile();
tempFile.deleteOnExit();

doc.save(tempFile.getAbsolutePath());

try (PDDocument doc2 = parse(SeekableSources.seekableSourceFrom(tempFile)))
{
PDPage p = doc.getPage(0);
COSBase value = PDPageTree.getInheritableAttribute(p.getCOSObject(), COSName.D);
assertNull(value);
}
finally
{
tempFile.delete();
}
}
}

0 comments on commit 5821e48

Please sign in to comment.