[Okular-devel] branches/KDE/3.5/kdegraphics/kpdf/xpdf/xpdf

Albert Astals Cid tsdgeos at terra.es
Wed Jan 10 21:12:13 CET 2007


SVN commit 622127 by aacid:

Keep a set of the already read page tree nodes and each time we follow a new one check if we already processed it so we don't end in a infinite loop.
Fixes crash in malicious pdf found at http://projects.info-pull.com/moab/MOAB-06-01-2007.html
It may seem quite intensive but my measurements indicate the page tree processing is I/O bound as i got the same average times with and without this patch. Obviously if anyone wants to measure more it'll be appreciated.
CCMAIL: okular-devel at kde.org
CCMAIL: security at kde.org


 M  +2 -0      Array.h  
 M  +18 -7     Catalog.cc  
 M  +3 -1      Catalog.h  


--- branches/KDE/3.5/kdegraphics/kpdf/xpdf/xpdf/Array.h #622126:622127
@@ -47,6 +47,8 @@
   Object *getNF(int i, Object *obj);
   GBool getString(int i, GString *string);
 
+  XRef *getXRef() { return xref; }
+
 private:
 
   XRef *xref;			// the xref table for this PDF file
--- branches/KDE/3.5/kdegraphics/kpdf/xpdf/xpdf/Catalog.cc #622126:622127
@@ -35,6 +35,7 @@
   Object obj, obj2;
   int numPages0;
   int i;
+  std::set< std::pair<int, int> > readNodes;
 
   ok = gTrue;
   xref = xrefA;
@@ -51,7 +52,9 @@
   }
 
   // read page tree
-  catDict.dictLookup("Pages", &pagesDict);
+  catDict.dictLookupNF("Pages", &pagesDict);
+  readNodes.insert( std::pair<int, int>(pagesDict.getRef().num, pagesDict.getRef().gen) );
+  pagesDict.fetch(xref, &pagesDict);
   // This should really be isDict("Pages"), but I've seen at least one
   // PDF file where the /Type entry is missing.
   if (!pagesDict.isDict()) {
@@ -76,7 +79,7 @@
     pageRefs[i].num = -1;
     pageRefs[i].gen = -1;
   }
-  numPages = readPageTree(pagesDict.getDict(), NULL, 0);
+  numPages = readPageTree(pagesDict.getDict(), NULL, 0, readNodes);
   if (numPages != numPages0) {
     error(-1, "Page count in top-level pages object is incorrect");
   }
@@ -191,7 +194,7 @@
   return s;
 }
 
-int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
+int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start, std::set< std::pair<int, int> > &readNodes) {
   Object kids;
   Object kid;
   Object kidRef;
@@ -207,7 +210,9 @@
     goto err1;
   }
   for (i = 0; i < kids.arrayGetLength(); ++i) {
-    kids.arrayGet(i, &kid);
+    kids.arrayGetNF(i, &kid);
+    const Ref &ref = kid.getRef();
+    kid.fetch(kids.getArray()->getXRef(), &kid);
     if (kid.isDict("Page")) {
       attrs2 = new PageAttrs(attrs1, kid.getDict());
       page = new Page(xref, start+1, kid.getDict(), attrs2);
@@ -236,9 +241,15 @@
     // This should really be isDict("Pages"), but I've seen at least one
     // PDF file where the /Type entry is missing.
     } else if (kid.isDict()) {
-      if ((start = readPageTree(kid.getDict(), attrs1, start))
-	  < 0)
-	goto err2;
+      std::pair<int, int> node(ref.num, ref.gen);
+      std::pair< std::set< std::pair<int, int> >::iterator, bool> insertResult = readNodes.insert(node);
+      if (insertResult.second) {
+        if ((start = readPageTree(kid.getDict(), attrs1, start, readNodes))
+	    < 0)
+	  goto err2;
+      } else {
+       error(-1, "Kid object was already processed. The pdf is faulty.");
+      }
     } else {
       error(-1, "Kid object (page %d) is wrong type (%s)",
 	    start+1, kid.getTypeName());
--- branches/KDE/3.5/kdegraphics/kpdf/xpdf/xpdf/Catalog.h #622126:622127
@@ -11,6 +11,8 @@
 
 #include <aconf.h>
 
+#include <set>
+
 #ifdef USE_GCC_PRAGMAS
 #pragma interface
 #endif
@@ -128,7 +130,7 @@
   Object acroForm;		// AcroForm dictionary
   GBool ok;			// true if catalog is valid
 
-  int readPageTree(Dict *pages, PageAttrs *attrs, int start);
+  int readPageTree(Dict *pages, PageAttrs *attrs, int start, std::set< std::pair<int, int> > &readNodes);
   Object *findDestInTree(Object *tree, GString *name, Object *obj);
 };
 


More information about the Okular-devel mailing list