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 2015/03/22 14:22:02 UTC

svn commit: r1668365 - /pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java

Author: lehmi
Date: Sun Mar 22 13:22:02 2015
New Revision: 1668365

URL: http://svn.apache.org/r1668365
Log:
PDFBOX-2679: Improved object key check to find wrong offsets within the xref table

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

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java?rev=1668365&r1=1668364&r2=1668365&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java Sun Mar 22 13:22:02 2015
@@ -46,11 +46,11 @@ import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSNull;
 import org.apache.pdfbox.cos.COSNumber;
 import org.apache.pdfbox.cos.COSObject;
+import org.apache.pdfbox.cos.COSObjectKey;
 import org.apache.pdfbox.cos.COSStream;
 import org.apache.pdfbox.io.IOUtils;
 import org.apache.pdfbox.pdfparser.XrefTrailerResolver.XRefType;
 import org.apache.pdfbox.pdmodel.encryption.SecurityHandler;
-import org.apache.pdfbox.cos.COSObjectKey;
 
 /**
  * PDF-Parser which first reads startxref and xref tables in order to know valid objects and parse only these objects.
@@ -1148,6 +1148,7 @@ public class COSParser extends BaseParse
             return;
         }
         Map<COSObjectKey, Long> xrefOffset = xrefTrailerResolver.getXrefTable();
+        Map<COSObjectKey, COSObjectKey> replacedKeys = new HashMap<COSObjectKey,COSObjectKey>();
         if (xrefOffset != null)
         {
             for (Entry<COSObjectKey, Long> objectEntry : xrefOffset.entrySet())
@@ -1158,11 +1159,12 @@ public class COSParser extends BaseParse
                 // see type 2 entry in xref stream
                 if (objectOffset != null && objectOffset >= 0)
                 {
-                    long objectNr = objectKey.getNumber();
-                    int objectGen = objectKey.getGeneration();
-                    String objectString = createObjectString(objectNr, objectGen);
-                    if (!checkObjectId(objectString, objectOffset))
+                    COSObjectKey newObjectKey = checkObjectKeys(objectKey,objectOffset);
+                    if (newObjectKey == null)
                     {
+                        long objectNr = objectKey.getNumber();
+                        int objectGen = objectKey.getGeneration();
+                        String objectString = createObjectString(objectNr, objectGen);
                         long newOffset = bfSearchForObject(objectString);
                         if (newOffset > -1)
                         {
@@ -1176,29 +1178,84 @@ public class COSParser extends BaseParse
                                     + " (origin offset " + objectOffset + ")");
                         }
                     }
+                    else if (!objectKey.equals(newObjectKey))
+                    {
+                        replacedKeys.put(objectKey, newObjectKey);
+                    }
                 }
             }
         }
-        // TODO cross check found objects
+        // are there any replaced object keys
+        if (!replacedKeys.isEmpty())
+        {
+            Map<COSObjectKey,Long> offsets = new HashMap<COSObjectKey, Long>(replacedKeys.size());
+            for (COSObjectKey oldObjectKey : replacedKeys.keySet())
+            {
+                // remove to be replaced entries first
+                offsets.put(oldObjectKey, xrefOffset.remove(oldObjectKey));
+            }
+            for (COSObjectKey oldObjectKey : replacedKeys.keySet())
+            {
+                COSObjectKey newObjectKey = replacedKeys.get(oldObjectKey);
+                // add mapped entry
+                xrefOffset.put(newObjectKey, offsets.get(oldObjectKey));
+                LOG.debug("Object key replaced within xref table: " + oldObjectKey + " -> " + newObjectKey);
+            }
+        }
     }
 
     /**
-     * Check if the given string can be found at the given offset.
+     * Check if the given object can be found at the given offset.
+     * 
+     * Returns the given object key if the object can be found.
+     * Returns a new object key if an object can be found but the number doesn't fit.
+     * Returns null if non valid object can be found at the given offset.
      * 
-     * @param objectString the string we are looking for
-     * @param offset the given where to look
-     * @return returns true if the given string can be found at the givwen offset
+     * @param objectKey the object we are looking for
+     * @param offset the offset where to look
+     * @return returns the object key of the object at the given offset
      * @throws IOException if something went wrong
      */
-    private boolean checkObjectId(String objectString, long offset) throws IOException
+    private COSObjectKey checkObjectKeys(COSObjectKey objectKey, long offset) throws IOException
     {
+        long objectNr = objectKey.getNumber();
+        int objectGen = objectKey.getGeneration();
         long originOffset = pdfSource.getOffset();
         pdfSource.seek(offset);
-        boolean objectFound = isString(objectString.getBytes(ISO_8859_1));
-        pdfSource.seek(originOffset);
-        return objectFound;
+        String objectString = createObjectString(objectNr, objectGen);
+        if (isString(objectString.getBytes(ISO_8859_1)))
+        {
+            // everything is ok, return origin object key
+            pdfSource.seek(originOffset);
+            return objectKey;
+        }
+        try 
+        {
+            // can't find the object key, maybe we are looking for the wrong number
+            pdfSource.seek(offset);
+            long objectNrRead = readLong();
+            if (objectNrRead > 0)
+            {
+                skipSpaces();
+                int objectGenRead = readInt();
+                if (objectGenRead >= 0)
+                {
+                    // found a valid object number, return a new COSObjectKey
+                    return new COSObjectKey(objectNrRead, objectGenRead);
+                }
+            }
+        }
+        catch (IOException exception)
+        {
+            // Swallow the exception, obviously there isn't any valid object number
+        }
+        finally 
+        {
+            pdfSource.seek(originOffset);
+        }
+        // no valid object number found
+        return null;
     }
-
     /**
      * Create a string for the given object id.
      *