[poppler] poppler/Dict.cc poppler/Dict.h poppler/Object.cc poppler/Object.h poppler/Parser.cc poppler/Parser.h poppler/XRef.cc poppler/XRef.h

Albert Astals Cid aacid at kemper.freedesktop.org
Sat Nov 20 14:15:55 PST 2010


 poppler/Dict.cc   |    4 ++--
 poppler/Dict.h    |    2 +-
 poppler/Object.cc |    4 ++--
 poppler/Object.h  |    9 +++++----
 poppler/Parser.cc |   19 +++++++++++++------
 poppler/Parser.h  |    7 ++++++-
 poppler/XRef.cc   |   30 +++++++++++++++++++++++++-----
 poppler/XRef.h    |    2 +-
 8 files changed, 55 insertions(+), 22 deletions(-)

New commits:
commit 3628837febb21bcd1b54f3fb737628ea59e5d95d
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sat Nov 20 22:15:08 2010 +0000

    And now generalize the previous fix
    
    Works for loops of more than one item as in bug 28784

diff --git a/poppler/Dict.cc b/poppler/Dict.cc
index 9749c25..2318e69 100644
--- a/poppler/Dict.cc
+++ b/poppler/Dict.cc
@@ -189,10 +189,10 @@ GBool Dict::is(char *type) {
   return (e = find("Type")) && e->val.isName(type);
 }
 
-Object *Dict::lookup(char *key, Object *obj, int fetchOriginatorNum) {
+Object *Dict::lookup(char *key, Object *obj, std::set<int> *fetchOriginatorNums) {
   DictEntry *e;
 
-  return (e = find(key)) ? e->val.fetch(xref, obj, fetchOriginatorNum) : obj->initNull();
+  return (e = find(key)) ? e->val.fetch(xref, obj, fetchOriginatorNums) : obj->initNull();
 }
 
 Object *Dict::lookupNF(char *key, Object *obj) {
diff --git a/poppler/Dict.h b/poppler/Dict.h
index bab0277..95c596c 100644
--- a/poppler/Dict.h
+++ b/poppler/Dict.h
@@ -72,7 +72,7 @@ public:
 
   // Look up an entry and return the value.  Returns a null object
   // if <key> is not in the dictionary.
-  Object *lookup(char *key, Object *obj, int fetchOriginatorNum = -1);
+  Object *lookup(char *key, Object *obj, std::set<int> *fetchOriginatorNums = NULL);
   Object *lookupNF(char *key, Object *obj);
   GBool lookupInt(const char *key, const char *alt_key, int *value);
 
diff --git a/poppler/Object.cc b/poppler/Object.cc
index af89c29..4f7da80 100644
--- a/poppler/Object.cc
+++ b/poppler/Object.cc
@@ -115,9 +115,9 @@ Object *Object::copy(Object *obj) {
   return obj;
 }
 
-Object *Object::fetch(XRef *xref, Object *obj, int fetchOriginatorNum) {
+Object *Object::fetch(XRef *xref, Object *obj, std::set<int> *fetchOriginatorNums) {
   return (type == objRef && xref) ?
-         xref->fetch(ref.num, ref.gen, obj, fetchOriginatorNum) : copy(obj);
+         xref->fetch(ref.num, ref.gen, obj, fetchOriginatorNums) : copy(obj);
 }
 
 void Object::free() {
diff --git a/poppler/Object.h b/poppler/Object.h
index 8dd9063..72ff667 100644
--- a/poppler/Object.h
+++ b/poppler/Object.h
@@ -30,6 +30,7 @@
 #pragma interface
 #endif
 
+#include <set>
 #include <stdio.h>
 #include <string.h>
 #include "goo/gtypes.h"
@@ -153,7 +154,7 @@ public:
 
   // If object is a Ref, fetch and return the referenced object.
   // Otherwise, return a copy of the object.
-  Object *fetch(XRef *xref, Object *obj, int fetchOriginatorNum = -1);
+  Object *fetch(XRef *xref, Object *obj, std::set<int> *fetchOriginatorNums = NULL);
 
   // Free object contents.
   void free();
@@ -212,7 +213,7 @@ public:
   void dictAdd(char *key, Object *val);
   void dictSet(char *key, Object *val);
   GBool dictIs(char *dictType);
-  Object *dictLookup(char *key, Object *obj, int fetchOriginatorNum = -1);
+  Object *dictLookup(char *key, Object *obj, std::set<int> *fetchOriginatorNums = NULL);
   Object *dictLookupNF(char *key, Object *obj);
   char *dictGetKey(int i);
   Object *dictGetVal(int i, Object *obj);
@@ -299,8 +300,8 @@ inline GBool Object::dictIs(char *dictType)
 inline GBool Object::isDict(char *dictType)
   { return type == objDict && dictIs(dictType); }
 
-inline Object *Object::dictLookup(char *key, Object *obj, int fetchOriginatorNum)
-  { OBJECT_TYPE_CHECK(objDict); return dict->lookup(key, obj, fetchOriginatorNum); }
+inline Object *Object::dictLookup(char *key, Object *obj, std::set<int> *fetchOriginatorNums)
+  { OBJECT_TYPE_CHECK(objDict); return dict->lookup(key, obj, fetchOriginatorNums); }
 
 inline Object *Object::dictLookupNF(char *key, Object *obj)
   { OBJECT_TYPE_CHECK(objDict); return dict->lookupNF(key, obj); }
diff --git a/poppler/Parser.cc b/poppler/Parser.cc
index 8ee927c..85383cc 100644
--- a/poppler/Parser.cc
+++ b/poppler/Parser.cc
@@ -53,8 +53,15 @@ Parser::~Parser() {
 }
 
 Object *Parser::getObj(Object *obj, Guchar *fileKey,
+           CryptAlgorithm encAlgorithm, int keyLength,
+           int objNum, int objGen) {
+  std::set<int> fetchOriginatorNums;
+  return getObj(obj, fileKey, encAlgorithm, keyLength, objNum, objGen, &fetchOriginatorNums);
+}
+
+Object *Parser::getObj(Object *obj, Guchar *fileKey,
 		       CryptAlgorithm encAlgorithm, int keyLength,
-		       int objNum, int objGen) {
+		       int objNum, int objGen, std::set<int> *fetchOriginatorNums) {
   char *key;
   Stream *str;
   Object obj2;
@@ -78,7 +85,7 @@ Object *Parser::getObj(Object *obj, Guchar *fileKey,
     obj->initArray(xref);
     while (!buf1.isCmd("]") && !buf1.isEOF())
       obj->arrayAdd(getObj(&obj2, fileKey, encAlgorithm, keyLength,
-			   objNum, objGen));
+			   objNum, objGen, fetchOriginatorNums));
     if (buf1.isEOF())
       error(getPos(), "End of file inside array");
     shift();
@@ -99,7 +106,7 @@ Object *Parser::getObj(Object *obj, Guchar *fileKey,
 	  gfree(key);
 	  break;
 	}
-	obj->dictAdd(key, getObj(&obj2, fileKey, encAlgorithm, keyLength, objNum, objGen));
+	obj->dictAdd(key, getObj(&obj2, fileKey, encAlgorithm, keyLength, objNum, objGen, fetchOriginatorNums));
       }
     }
     if (buf1.isEOF())
@@ -108,7 +115,7 @@ Object *Parser::getObj(Object *obj, Guchar *fileKey,
     // object streams
     if (allowStreams && buf2.isCmd("stream")) {
       if ((str = makeStream(obj, fileKey, encAlgorithm, keyLength,
-			    objNum, objGen))) {
+			    objNum, objGen, fetchOriginatorNums))) {
 	obj->initStream(str);
       } else {
 	obj->free();
@@ -162,7 +169,7 @@ Object *Parser::getObj(Object *obj, Guchar *fileKey,
 
 Stream *Parser::makeStream(Object *dict, Guchar *fileKey,
 			   CryptAlgorithm encAlgorithm, int keyLength,
-			   int objNum, int objGen) {
+			   int objNum, int objGen, std::set<int> *fetchOriginatorNums) {
   Object obj;
   BaseStream *baseStr;
   Stream *str;
@@ -173,7 +180,7 @@ Stream *Parser::makeStream(Object *dict, Guchar *fileKey,
   pos = lexer->getPos();
 
   // get length
-  dict->dictLookup("Length", &obj, objNum);
+  dict->dictLookup("Length", &obj, fetchOriginatorNums);
   if (obj.isInt()) {
     length = (Guint)obj.getInt();
     obj.free();
diff --git a/poppler/Parser.h b/poppler/Parser.h
index d09b23b..1420984 100644
--- a/poppler/Parser.h
+++ b/poppler/Parser.h
@@ -46,6 +46,11 @@ public:
   Object *getObj(Object *obj, Guchar *fileKey = NULL,
 		 CryptAlgorithm encAlgorithm = cryptRC4, int keyLength = 0,
 		 int objNum = 0, int objGen = 0);
+  
+  Object *getObj(Object *obj, Guchar *fileKey,
+     CryptAlgorithm encAlgorithm, int keyLength,
+     int objNum, int objGen, std::set<int> *fetchOriginatorNums);
+
 
   // Get stream.
   Stream *getStream() { return lexer->getStream(); }
@@ -63,7 +68,7 @@ private:
 
   Stream *makeStream(Object *dict, Guchar *fileKey,
 		     CryptAlgorithm encAlgorithm, int keyLength,
-		     int objNum, int objGen);
+		     int objNum, int objGen, std::set<int> *fetchOriginatorNums);
   void shift(int objNum = -1);
 };
 
diff --git a/poppler/XRef.cc b/poppler/XRef.cc
index c7cdc89..dd7950f 100644
--- a/poppler/XRef.cc
+++ b/poppler/XRef.cc
@@ -967,14 +967,16 @@ GBool XRef::okToAssemble(GBool ignoreOwnerPW) {
   return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permAssemble);
 }
 
-Object *XRef::fetch(int num, int gen, Object *obj, int fetchOriginatorNum) {
+Object *XRef::fetch(int num, int gen, Object *obj, std::set<int> *fetchOriginatorNums) {
   XRefEntry *e;
   Parser *parser;
   Object obj1, obj2, obj3;
+  bool deleteFetchOriginatorNums = false;
+  std::pair<std::set<int>::iterator, bool> fetchInsertResult;
 
   // check for bogus ref - this can happen in corrupted PDF files
-  if (num < 0 || num >= size || num == fetchOriginatorNum) {
-    goto err;
+  if (num < 0 || num >= size || (fetchOriginatorNums != NULL && fetchOriginatorNums->find(num) != fetchOriginatorNums->end())) {
+    goto err2;
   }
 
   e = getEntry(num);
@@ -982,6 +984,13 @@ Object *XRef::fetch(int num, int gen, Object *obj, int fetchOriginatorNum) {
     obj = e->obj.copy(obj);
     return obj;
   }
+
+  if (fetchOriginatorNums == NULL) {
+    fetchOriginatorNums = new std::set<int>();
+    deleteFetchOriginatorNums = true;
+  }
+  fetchInsertResult = fetchOriginatorNums->insert(num);
+
   switch (e->type) {
 
   case xrefEntryUncompressed:
@@ -1030,7 +1039,7 @@ Object *XRef::fetch(int num, int gen, Object *obj, int fetchOriginatorNum) {
       goto err;
     }
     parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL,
-		   encAlgorithm, keyLength, num, gen);
+		   encAlgorithm, keyLength, num, gen, fetchOriginatorNums);
     obj1.free();
     obj2.free();
     obj3.free();
@@ -1070,10 +1079,21 @@ Object *XRef::fetch(int num, int gen, Object *obj, int fetchOriginatorNum) {
   default:
     goto err;
   }
-
+  
+  if (deleteFetchOriginatorNums) {
+    delete fetchOriginatorNums;
+  } else {
+    fetchOriginatorNums->erase(fetchInsertResult.first);
+  }
   return obj;
 
  err:
+  if (deleteFetchOriginatorNums) {
+    delete fetchOriginatorNums;
+  } else {
+    fetchOriginatorNums->erase(fetchInsertResult.first);
+  }
+ err2:
   return obj->initNull();
 }
 
diff --git a/poppler/XRef.h b/poppler/XRef.h
index de11428..ce4e9fe 100644
--- a/poppler/XRef.h
+++ b/poppler/XRef.h
@@ -101,7 +101,7 @@ public:
   Object *getCatalog(Object *obj) { return fetch(rootNum, rootGen, obj); }
 
   // Fetch an indirect reference.
-  Object *fetch(int num, int gen, Object *obj, int fetchOriginatorNum = -1);
+  Object *fetch(int num, int gen, Object *obj, std::set<int> *fetchOriginatorNums = NULL);
 
   // Return the document's Info dictionary (if any).
   Object *getDocInfo(Object *obj);


More information about the poppler mailing list