--- kpdf/xpdf/Catalog.cc
+++ kpdf/xpdf/Catalog.cc
@@ -23,6 +23,12 @@
#include "Link.h"
#include "Catalog.h"

+// This define is used to limit the depth of recursive readPageTree calls
+// This is needed because the page tree nodes can reference their parents
+// leaving us in an infinite loop
+// Most sane pdf documents don't have a call depth higher than 10
+#define MAX_CALL_DEPTH 1000
+
//------------------------------------------------------------------------
// Catalog
//------------------------------------------------------------------------
@@ -76,7 +82,7 @@
    pageRefs[i].num = -1;
    pageRefs[i].gen = -1;
  }
-  numPages = readPageTree(pagesDict.getDict(), NULL, 0);
+  numPages = readPageTree(pagesDict.getDict(), NULL, 0, 0);
  if (numPages != numPages0) {
    error(-1, "Page count in top-level pages object is incorrect");
  }
@@ -170,7 +176,7 @@
  return s;
}

-int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
+int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start, int callDepth) {
  Object kids;
  Object kid;
  Object kidRef;
@@ -220,9 +226,13 @@
    // 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;
+      if (callDepth > MAX_CALL_DEPTH) {
+        error(-1, "Limit of %d recursive calls reached while reading the page tree. If your document is correct and not a test to try to force a crash, please report a bug.", MAX_CALL_DEPTH);
+      } else {
+        if ((start = readPageTree(kid.getDict(), attrs1, start, callDepth + 1))
+           < 0)
+         goto err2;
+      }
    } else {
      error(-1, "Kid object (page %d) is wrong type (%s)",
           start+1, kid.getTypeName());
--- kpdf/xpdf/Catalog.h
+++ kpdf/xpdf/Catalog.h
@@ -82,7 +82,7 @@
  Object outline;              // outline dictionary
  GBool ok;                    // true if catalog is valid

-  int readPageTree(Dict *pages, PageAttrs *attrs, int start);
+  int readPageTree(Dict *pages, PageAttrs *attrs, int start, int callDepth);
  Object *findDestInTree(Object *tree, GString *name, Object *obj);
};