You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2017/05/11 05:43:28 UTC

svn commit: r1794782 - /pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java

Author: lehmi
Date: Thu May 11 05:43:28 2017
New Revision: 1794782

URL: http://svn.apache.org/viewvc?rev=1794782&view=rev
Log:
PDFBOX-3788: revert former changes due to a regression

Modified:
    pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java

Modified: pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java?rev=1794782&r1=1794781&r2=1794782&view=diff
==============================================================================
--- pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java (original)
+++ pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java Thu May 11 05:43:28 2017
@@ -313,13 +313,9 @@ public class COSParser extends BaseParse
         document.setTrailer(trailer);
         document.setIsXRefStream(XRefType.STREAM == xrefTrailerResolver.getXrefType());
         // check the offsets of all referenced objects
-        Map<COSObjectKey, Long> xrefOffset = xrefTrailerResolver.getXrefTable();
-        if (isLenient && !validateXrefOffsets(xrefOffset))
-        {
-            throw new IOException("Invalid object reference found");
-        }
+        checkXrefOffsets();
         // copy xref table
-        document.addXRefTable(xrefOffset);
+        document.addXRefTable(xrefTrailerResolver.getXrefTable());
         return trailer;
     }
 
@@ -1296,6 +1292,77 @@ public class COSParser extends BaseParse
     }
 
     /**
+     * Check the XRef table by dereferencing all objects and fixing the offset if necessary.
+     * 
+     * @throws IOException if something went wrong.
+     */
+    private void checkXrefOffsets() throws IOException
+    {
+        // repair mode isn't available in non-lenient mode
+        if (!isLenient)
+        {
+            return;
+        }
+        Map<COSObjectKey, Long> xrefOffset = xrefTrailerResolver.getXrefTable();
+        if (!validateXrefOffsets(xrefOffset))
+        {
+            bfSearchForObjects();
+            if (bfSearchCOSObjectKeyOffsets != null && !bfSearchCOSObjectKeyOffsets.isEmpty())
+            {
+                List<COSObjectKey> objStreams = new ArrayList<COSObjectKey>();
+                // find all object streams
+                for (COSObjectKey key : xrefOffset.keySet())
+                {
+                    Long offset = xrefOffset.get(key);
+                    if (offset != null && offset < 0)
+                    {
+                        COSObjectKey objStream = new COSObjectKey(-offset, 0);
+                        if (!objStreams.contains(objStream))
+                        {
+                            objStreams.add(new COSObjectKey(-offset, 0));
+                        }
+                    }
+                }
+                // remove all found object streams
+                if (!objStreams.isEmpty())
+                {
+                    for (COSObjectKey key : objStreams)
+                    {
+                        if (bfSearchCOSObjectKeyOffsets.containsKey(key))
+                        {
+                            // remove all parsed objects which are part of an object stream
+                            Set<Long> objects = xrefTrailerResolver
+                                    .getContainedObjectNumbers((int) (key.getNumber()));
+                            for (Long objNr : objects)
+                            {
+                                COSObjectKey streamObjectKey = new COSObjectKey(objNr, 0);
+                                Long streamObjectOffset = bfSearchCOSObjectKeyOffsets
+                                        .get(streamObjectKey);
+                                if (streamObjectOffset != null && streamObjectOffset > 0)
+                                {
+                                    bfSearchCOSObjectKeyOffsets.remove(streamObjectKey);
+                                }
+                            }
+                        }
+                        else
+                        {
+                            // remove all objects which are part of an object stream which wasn't found
+                            Set<Long> objects = xrefTrailerResolver
+                                    .getContainedObjectNumbers((int) (key.getNumber()));
+                            for (Long objNr : objects)
+                            {
+                                xrefOffset.remove(new COSObjectKey(objNr, 0));
+                            }
+                        }
+                    }
+                }
+                LOG.debug("Replaced read xref table with the results of a brute force search");
+                xrefOffset.putAll(bfSearchCOSObjectKeyOffsets);
+            }
+        }
+    }
+
+    /**
      * Check if the given object can be found at the given offset.
      * 
      * @param objectKey the object we are looking for