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 2020/01/03 14:17:14 UTC

svn commit: r1872289 - in /pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser: COSParser.java PDFObjectStreamParser.java

Author: lehmi
Date: Fri Jan  3 14:17:13 2020
New Revision: 1872289

URL: http://svn.apache.org/viewvc?rev=1872289&view=rev
Log:
PDFBOX-4569: refactor brute force parser, use ondemand parser and remove redundant code

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

Modified: pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java?rev=1872289&r1=1872288&r2=1872289&view=diff
==============================================================================
--- pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java (original)
+++ pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/COSParser.java Fri Jan  3 14:17:13 2020
@@ -38,7 +38,6 @@ import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSDocument;
-import org.apache.pdfbox.cos.COSInputStream;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSNull;
 import org.apache.pdfbox.cos.COSNumber;
@@ -568,7 +567,8 @@ public class COSParser extends BaseParse
     public boolean dereferenceCOSObject(COSObject obj) throws IOException
     {
         long currentPos = source.getPosition();
-        COSBase parsedObj = parseObjectDynamically(obj, false);
+        COSBase parsedObj = parseObjectDynamically(obj.getObjectNumber(), obj.getGenerationNumber(),
+                false);
         if (currentPos > 0)
         {
             source.seek(currentPos);
@@ -577,25 +577,7 @@ public class COSParser extends BaseParse
     }
 
     /**
-     * This will parse the next object from the stream and add it to the local state. 
-     * 
-     * @param obj object to be parsed (we only take object number and generation number for lookup start offset)
-     * @param requireExistingNotCompressedObj if <code>true</code> object to be parsed must not be contained within
-     * compressed stream
-     * @return the parsed object (which is also added to document object)
-     * 
-     * @throws IOException If an IO error occurs.
-     */
-    protected final COSBase parseObjectDynamically(COSObject obj,
-            boolean requireExistingNotCompressedObj) throws IOException
-    {
-        return parseObjectDynamically(obj.getObjectNumber(), 
-                obj.getGenerationNumber(), requireExistingNotCompressedObj);
-    }
-
-    /**
      * Parse the object for the given object number.  
-     * It's reduced to parsing an indirect object.
      * 
      * @param objNr object number of object to be parsed
      * @param objGenNr object generation number of object to be parsed
@@ -1652,31 +1634,32 @@ public class COSParser extends BaseParse
             long stmObjNumber = readObjectNumber();
             int stmGenNumber = readGenerationNumber();
             readExpectedString(OBJ_MARKER, true);
-            int nrOfObjects = 0;
-            byte[] numbersBytes = null;
             COSStream stream = null;
-            COSInputStream is = null;
             try
             {
                 COSDictionary dict = parseCOSDictionary();
-                int offsetFirstStream = dict.getInt(COSName.FIRST);
-                nrOfObjects = dict.getInt(COSName.N);
-                // skip the stream if required values are missing
-                if (offsetFirstStream != -1 && nrOfObjects != -1)
+                stream = parseCOSStream(dict);
+                if (securityHandler != null)
                 {
-                    stream = parseCOSStream(dict);
-                    if (securityHandler != null)
-                    {
-                        securityHandler.decryptStream(stream, stmObjNumber, stmGenNumber);
+                    securityHandler.decryptStream(stream, stmObjNumber, stmGenNumber);
+                }
+                PDFObjectStreamParser objStreamParser = new PDFObjectStreamParser(stream, document);
+                Map<Long, Integer> objectNumbers = objStreamParser.readObjectNumbers();
+                Map<COSObjectKey, Long> xrefOffset = xrefTrailerResolver.getXrefTable();
+                for (Long objNumber : objectNumbers.keySet())
+                {
+                    COSObjectKey objKey = new COSObjectKey(objNumber, 0);
+                    Long existingOffset = bfSearchCOSObjectKeyOffsets.get(objKey);
+                    if (existingOffset != null && existingOffset < 0)
+                    {
+                        // translate stream object key to its offset
+                        COSObjectKey objStmKey = new COSObjectKey(Math.abs(existingOffset), 0);
+                        existingOffset = bfSearchCOSObjectKeyOffsets.get(objStmKey);
                     }
-                    is = stream.createInputStream();
-                    numbersBytes = new byte[offsetFirstStream];
-                    long isResult = is.read(numbersBytes);
-
-                    if (Long.compare(isResult, numbersBytes.length) != 0)
+                    if (existingOffset == null || offset > existingOffset)
                     {
-                        LOG.debug("Tried reading " + numbersBytes.length + " bytes but only "
-                                + isResult + " bytes read");
+                        bfSearchCOSObjectKeyOffsets.put(objKey, -stmObjNumber);
+                        xrefOffset.put(objKey, -stmObjNumber);
                     }
                 }
             }
@@ -1687,55 +1670,11 @@ public class COSParser extends BaseParse
             }
             finally
             {
-                if (is != null)
-                {
-                    is.close();
-                }
                 if (stream != null)
                 {
                     stream.close();
                 }
             }
-            if (numbersBytes != null)
-            {
-                // convert byte array to string, skip leading/trailing spaces, replace LF\double spaces
-                String[] numbers = new String(numbersBytes, StandardCharsets.ISO_8859_1) //
-                        .trim() //
-                        .replaceAll("\n", " ") //
-                        .replace("  ", " ") //
-                        .split(" ");
-                if (numbers.length < nrOfObjects * 2)
-                {
-                    LOG.debug(
-                            "Skipped corrupt stream: (" + stmObjNumber + " 0 at offset " + offset);
-                    continue;
-                }
-                Map<COSObjectKey, Long> xrefOffset = xrefTrailerResolver.getXrefTable();
-                for (int i = 0; i < nrOfObjects; i++)
-                {
-                    try
-                    {
-                        long objNumber = Long.parseLong(numbers[i * 2]);
-                        COSObjectKey objKey = new COSObjectKey(objNumber, 0);
-                        Long existingOffset = bfSearchCOSObjectKeyOffsets.get(objKey);
-                        if (existingOffset != null && existingOffset < 0)
-                        {
-                            // translate stream object key to its offset
-                            COSObjectKey objStmKey = new COSObjectKey(Math.abs(existingOffset), 0);
-                            existingOffset = bfSearchCOSObjectKeyOffsets.get(objStmKey);
-                        }
-                        if (existingOffset == null || offset > existingOffset)
-                        {
-                            bfSearchCOSObjectKeyOffsets.put(objKey, -stmObjNumber);
-                            xrefOffset.put(objKey, -stmObjNumber);
-                        }
-                    }
-                    catch (NumberFormatException exception)
-                    {
-                        LOG.debug("Skipped corrupt object key in stream: " + stmObjNumber);
-                    }
-                }
-            }
         }
         // restore origin offset
         source.seek(originOffset);

Modified: pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFObjectStreamParser.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFObjectStreamParser.java?rev=1872289&r1=1872288&r2=1872289&view=diff
==============================================================================
--- pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFObjectStreamParser.java (original)
+++ pdfbox/branches/issue4569/pdfbox/src/main/java/org/apache/pdfbox/pdfparser/PDFObjectStreamParser.java Fri Jan  3 14:17:13 2020
@@ -63,6 +63,7 @@ public class PDFObjectStreamParser exten
 
     /**
      * Search for/parse the object with the given object number. This will close the stream when it is finished parsing.
+     * The stream is closed after parsing the object with the given number.
      * 
      * @param objectNumber the number of the object to b e parsed
      * @return the parsed object or null if the object with the given number can't be found
@@ -94,7 +95,14 @@ public class PDFObjectStreamParser exten
         return streamObject;
     }
 
-    private Map<Long, Integer> readObjectNumbers() throws IOException
+    /**
+     * Read all object numbers from the compressed object stream. The stream is not closed after reading the object
+     * numbers.
+     * 
+     * @return a map off all object numbers and the corresponding offset within the object stream.
+     * @throws IOException if there is an error while parsing the stream
+     */
+    public Map<Long, Integer> readObjectNumbers() throws IOException
     {
         Map<Long, Integer> objectNumbers = new HashMap<>(numberOfObjects);
         for (int i = 0; i < numberOfObjects; i++)
@@ -105,5 +113,4 @@ public class PDFObjectStreamParser exten
         }
         return objectNumbers;
     }
-
 }