Index: src/doc/PdfPagesTree.cpp
===================================================================
--- src/doc/PdfPagesTree.cpp	(revision 1935)
+++ src/doc/PdfPagesTree.cpp	(working copy)
@@ -423,6 +423,18 @@
                     else
                     {
                         rLstParents.push_back( pParent );
+
+                        if ( std::find( rLstParents.begin(), rLstParents.end(), pChild )
+                             != rLstParents.end() ) // cycle in parent list detected, fend
+                        { // off security vulnerability similar to CVE-2017-8054 (infinite recursion)
+                            std::ostringstream oss;
+                            oss << "Cycle in page tree: child in /Kids array of object "
+                                << ( *(rLstParents.rbegin()) )->Reference().ToString()
+                                << " back-references to object " << pChild->Reference()
+                                .ToString() << " one of whose descendants the former is.";
+                            PODOFO_RAISE_ERROR_INFO( ePdfError_PageNotFound, oss.str() );
+                        }
+
                         return this->GetPageNode( nPageNum, pChild, rLstParents );
                     }
                 }
Index: test/unit/PagesTreeTest.cpp
===================================================================
--- test/unit/PagesTreeTest.cpp	(revision 1935)
+++ test/unit/PagesTreeTest.cpp	(working copy)
@@ -22,6 +22,8 @@
 
 #include <podofo.h>
 
+#include <sstream>
+
 #define PODOFO_TEST_PAGE_KEY "PoDoFoTestPageNumber"
 #define PODOFO_TEST_NUM_PAGES 100
 
@@ -70,6 +72,32 @@
     CPPUNIT_ASSERT_THROW( writer.GetPage( 1 ), PdfError );
 }
 
+void PagesTreeTest::testCyclicTree()
+{
+    for (int run=0; run < 2; run++)
+    {
+        PdfMemDocument doc;
+        CreateCyclicTree( doc, run==1);
+
+        for (int pagenum=0; pagenum < doc.GetPageCount(); pagenum++)
+        {
+            if (run==0)
+            {    
+                // run 0:
+                // valid tree without cycles should yield all pages
+                PdfPage* pPage = doc.GetPage( pagenum );
+                CPPUNIT_ASSERT_EQUAL( pPage != NULL, true );
+            }
+            else
+            {
+                // run 1:
+                // cyclic tree must throw exception to prevent infinite recursion
+                CPPUNIT_ASSERT_THROW( doc.GetPage( pagenum ), PdfError );
+            }
+        }
+    }
+}
+
 void PagesTreeTest::testCreateDelete()
 {
     PdfMemDocument  writer;
@@ -354,7 +382,86 @@
     pRoot->GetDictionary().AddKey( PdfName("Count"), static_cast<pdf_int64>(PODOFO_TEST_NUM_PAGES) );
 }
 
+void PagesTreeTest::CreateCyclicTree( PoDoFo::PdfMemDocument & rDoc,
+                                      bool bCreateCycle )
+{
+    const int COUNT = 3;
+    PdfFont* pFont;
 
+    // create font
+    pFont = rDoc.CreateFont( "Arial" );
+    if( !pFont )
+    {
+        PODOFO_RAISE_ERROR( ePdfError_InvalidHandle );
+    }
+    pFont->SetFontSize( 16.0 );
+
+    // create pages
+    PdfPage* pPage[COUNT];
+    for (int i = 0; i < COUNT; ++i)
+    {
+        pPage[i] = new PdfPage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ),
+                                &(rDoc.GetObjects()) );
+
+        PdfPainter painter;
+        painter.SetPage( pPage[i] );
+        painter.SetFont( pFont );
+        std::ostringstream os;
+        os << "Page " << i+1;
+        painter.DrawText( 200, 200, os.str()  );
+        painter.FinishPage();
+    }
+    
+    // manually insert pages into pagetree
+    PdfObject* pRoot = rDoc.GetPagesTree()->GetObject();
+    PdfObject* pNode1 = rDoc.GetObjects().CreateObject("Pages");
+    PdfObject* pNode2 = rDoc.GetObjects().CreateObject("Pages");
+
+    // tree layout:
+    //
+    //    root
+    //    +-- node1
+    //        +--node2
+    //        |  +-- page0
+    //        |  +-- page1
+    //        \-- page2
+    
+    // root node
+    pRoot->GetDictionary().AddKey( PdfName("Count"), static_cast<pdf_int64>(COUNT) );
+    pRoot->GetDictionary().AddKey( PdfName("Kids"), PdfArray(pNode1->Reference()));
+
+    // tree node 1
+    pNode1->GetDictionary().AddKey( PdfName("Count"), static_cast<pdf_int64>(COUNT) );
+    PdfArray kids1;
+    if (bCreateCycle)
+    {
+        // invalid tree: Cycle!!!
+        // was not detected in PdfPagesTree::GetPageNode() rev. 1935
+        kids1.push_back(pRoot->Reference()); 
+    }
+    else
+    {
+        // correct tree
+        kids1.push_back(pNode2->Reference()); 
+    }    
+    kids1.push_back(pPage[2]->GetObject()->Reference());
+    pNode1->GetDictionary().AddKey( PdfName("Kids"), kids1);
+    pNode1->GetDictionary().AddKey( PdfName("Parent"), pRoot->Reference());
+    
+    pPage[2]->GetObject()->GetDictionary().AddKey ( PdfName("Parent"), pNode1->Reference());
+
+    // tree node 2
+    pNode2->GetDictionary().AddKey( PdfName("Count"), static_cast<pdf_int64>(2));
+    PdfArray kids2;
+    kids2.push_back(pPage[0]->GetObject()->Reference());
+    kids2.push_back(pPage[1]->GetObject()->Reference());
+    pNode2->GetDictionary().AddKey( PdfName("Kids"), kids2);
+    pNode2->GetDictionary().AddKey( PdfName("Parent"), pNode1->Reference());
+    
+    pPage[0]->GetObject()->GetDictionary().AddKey ( PdfName("Parent"), pNode2->Reference());
+    pPage[1]->GetObject()->GetDictionary().AddKey ( PdfName("Parent"), pNode2->Reference());
+}
+
 bool PagesTreeTest::IsPageNumber( PoDoFo::PdfPage* pPage, int nNumber )
 {
     pdf_int64 lPageNumber = pPage->GetObject()->GetDictionary().GetKeyAsLong( PODOFO_TEST_PAGE_KEY, -1 );
Index: test/unit/PagesTreeTest.h
===================================================================
--- test/unit/PagesTreeTest.h	(revision 1935)
+++ test/unit/PagesTreeTest.h	(working copy)
@@ -35,6 +35,7 @@
   CPPUNIT_TEST_SUITE( PagesTreeTest );
   CPPUNIT_TEST( testEmptyTree );
   CPPUNIT_TEST( testEmptyDoc );
+  CPPUNIT_TEST( testCyclicTree );
   CPPUNIT_TEST( testCreateDelete );
   CPPUNIT_TEST( testGetPagesCustom );
   CPPUNIT_TEST( testGetPagesPoDoFo );
@@ -52,6 +53,7 @@
 
   void testEmptyTree();
   void testEmptyDoc();
+  void testCyclicTree();
   void testCreateDelete();
   void testGetPagesCustom();
   void testGetPagesPoDoFo();
@@ -98,6 +100,9 @@
    */
   void CreateTestTreeCustom( PoDoFo::PdfMemDocument & rDoc );
 
+  void CreateCyclicTree( PoDoFo::PdfMemDocument & rDoc,
+                         bool bCreateCycle );
+
   bool IsPageNumber( PoDoFo::PdfPage* pPage, int nNumber );
 };
 
