Author: tilman
Date: Fri Sep 12 17:48:26 2025
New Revision: 1928375

Log:
PDFBOX-6067: check /ParentTree against /K tree; catch empty set

Modified:
   
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java

Modified: 
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java
==============================================================================
--- 
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java
       Fri Sep 12 17:48:22 2025        (r1928374)
+++ 
pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java
       Fri Sep 12 17:48:26 2025        (r1928375)
@@ -727,7 +727,8 @@ public class PDFMergerUtilityTest extend
                     }
                 }
                 // actual count may be larger if last element is null, e.g. 
PDFBOX-4408
-                assertTrue(set.last() <= array.size() - 1);
+                // set can be empty, see last page of pdf_32000_2008.pdf
+                assertTrue(set.isEmpty() || set.last() <= array.size() - 1);
             }
             for (PDAnnotation ann : page.getAnnotations())
             {
@@ -848,6 +849,34 @@ public class PDFMergerUtilityTest extend
         assertNotNull(structureTreeRoot.getK());
         checkElement(pageTree, structureTreeRoot.getK(), 
structureTreeRoot.getCOSObject());
         checkForIDTreeOrphans(pageTree, structureTreeRoot);
+        checkParentTreeAgainstK(structureTreeRoot);
+    }
+
+    private void checkParentTreeAgainstK(PDStructureTreeRoot 
structureTreeRoot) throws IOException
+    {
+        // check that elements in the /ParentTree are in the /K tree
+        ElementCounter elementCounter = new ElementCounter();
+        elementCounter.walk(structureTreeRoot.getK());
+        Map<Integer, COSObjectable> numberTreeAsMap = 
PDFMergerUtility.getNumberTreeAsMap(structureTreeRoot.getParentTree());
+        for (Map.Entry<Integer, COSObjectable> entry : 
numberTreeAsMap.entrySet())
+        {
+            PDParentTreeValue val = (PDParentTreeValue) entry.getValue(); // 
array or dictionary
+            COSBase base = val.getCOSObject();
+            if (base instanceof COSArray)
+            {
+                COSArray array = (COSArray) base;
+                for (int i = 0; i < array.size(); ++i)
+                {
+                    COSBase arrayElement = array.getObject(i);
+                    if (arrayElement instanceof COSDictionary)
+                    {
+                        assertTrue("Element " + entry.getKey() + ":" + i + " 
from /ParentTree missing in /K ",
+                                elementCounter.set.contains(arrayElement));
+                    }
+                }
+            }
+            // can't check this COSDictionary; ElementsCounter only counts 
those with a /Pg entry
+        }
     }
 
     private void checkForIDTreeOrphans(PDPageTree pageTree, 
PDStructureTreeRoot structureTreeRoot)

Reply via email to