Bug 1576174

Summary: (Excessive Iteration in PdfPagesTree::GetPageNode()) podofo Denial of Service
Product: [Fedora] Fedora EPEL Reporter: Zhiyuan Wang of Chengdu Qihoo360 Tech Co. Ltd <libfuzz>
Component: podofoAssignee: Dan Horák <dan>
Status: NEW --- QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: unspecified    
Version: epel7CC: carnil, dan, manisandro
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: All   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
crash demo file none

Description Zhiyuan Wang of Chengdu Qihoo360 Tech Co. Ltd 2018-05-09 04:22:55 UTC
Created attachment 1433509 [details]
crash demo file

Description of problem:
there is an Excessive Iteration in the PdfPagesTree::GetPageNode() function of PdfPagesTree.cpp:423. Remote attackers could leverage this vulnerability to cause a denial of service through a crafted pdf file.

Version-Release number of selected component (if applicable):
podofo 0.9.5

Detailed analysis of crash:
$ gdb podofomerge 
(gdb) r crash.pdf crash.pdf out.pdf
...
CRITICAL: Requesting page index 0. Invalid datatype referenced in kids array: Dictionary
Reference to invalid object: 1 0 R
CRITICAL: Requesting page index 0. Invalid datatype referenced in kids array: Dictionary
Reference to invalid object: 1 0 R
CRITICAL: Requesting page index 0. Invalid datatype referenced in kids array: Dictionary
Reference to invalid object: 1 0 R
CRITICAL: Requesting page index 0. Invalid datatype referenced in kids array: Dictionary
Reference to invalid object: 1 0 R
CRITICAL: Requesting page index 0. Invalid datatype referenced in kids array: Dictionary
Reference to invalid object: 1 0 R
CRITICAL: Requesting page index 0. Invalid datatype referenced in kids array: Dictionary
Reference to invalid object: 1 0 R
CRITICAL: Requesting page index 0. Invalid datatype referenced in kids array: Dictionary
Reference to invalid object: 1 0 R
CRITICAL: Requesting page index 0. Invalid datatype referenced in kids array: Dictionary
Reference to invalid object: 1 0 R
CRITICAL: Requesting page index 0. Invalid datatype referenced in kids array: Dictionary
Reference to invalid object: 1 0 R

Program received signal SIGSEGV, Segmentation fault.
0xb785b197 in __find_specmb (format=0xb7f79464 "%s") at printf-parse.h:108
108	printf-parse.h: No such file or directory.




(gdb) bt
#0  0xb785b197 in __find_specmb (format=0xb7f79464 "%s") at printf-parse.h:108
#1  _IO_vfprintf_internal (s=0xbf800538, format=0xb7f79464 "%s", ap=0xbf802b3c "5j\367\267Wqķ") at vfprintf.c:1312
#2  0xb785d671 in buffered_vfprintf (s=s@entry=0xb79cbcc0 <_IO_2_1_stderr_>, format=format@entry=0xb7f79464 "%s", args=args@entry=0xbf802b3c "5j\367\267Wqķ") at vfprintf.c:2320
#3  0xb785b2d1 in _IO_vfprintf_internal (s=0xb79cbcc0 <_IO_2_1_stderr_>, format=0xb7f79464 "%s", ap=0xbf802b3c "5j\367\267Wqķ") at vfprintf.c:1293
#4  0xb790e456 in ___fprintf_chk (fp=0xb79cbcc0 <_IO_2_1_stderr_>, flag=1, format=0xb7f79464 "%s") at fprintf_chk.c:35
#5  0xb7c47347 in fprintf (__fmt=0xb7f79464 "%s", __stream=<optimized out>) at /usr/include/i386-linux-gnu/bits/stdio2.h:98
#6  PoDoFo::PdfError::LogMessageInternal (eLogSeverity=PoDoFo::eLogSeverity_Critical, 
    pszMsg=0xb7f8a408 "Requesting page index %i. Invalid datatype referenced in kids array: %s\nReference to invalid object: %i %i R\n", args=@0xbf802b68: 0xbf802b88 "")
    at /home/zzuf/pdf-fuzz/podofo-0.9.5/src/base/PdfError.cpp:574
#7  0xb7c476aa in PoDoFo::PdfError::LogMessage (eLogSeverity=PoDoFo::eLogSeverity_Critical, 
    pszMsg=0xb7f8a408 "Requesting page index %i. Invalid datatype referenced in kids array: %s\nReference to invalid object: %i %i R\n") at /home/zzuf/pdf-fuzz/podofo-0.9.5/src/base/PdfError.cpp:528
#8  0xb7edd832 in PoDoFo::PdfPagesTree::GetPageNode (this=0x8062540, nPageNum=134615064, pParent=0x8061018, rLstParents=std::deque with 52325 elements = {...})
    at /home/zzuf/pdf-fuzz/podofo-0.9.5/src/doc/PdfPagesTree.cpp:447
#9  0xb7eddc8b in PoDoFo::PdfPagesTree::GetPageNode (this=0x8062540, nPageNum=134615064, pParent=0x8061018, rLstParents=std::deque with 52325 elements = {...})
    at /home/zzuf/pdf-fuzz/podofo-0.9.5/src/doc/PdfPagesTree.cpp:423
#10 0xb7eddc8b in PoDoFo::PdfPagesTree::GetPageNode (this=0x8062540, nPageNum=134615064, pParent=0x8061018, rLstParents=std::deque with 52325 elements = {...})
    at /home/zzuf/pdf-fuzz/podofo-0.9.5/src/doc/PdfPagesTree.cpp:423
#11 0xb7eddc8b in PoDoFo::PdfPagesTree::GetPageNode (this=0x8062540, nPageNum=134615064, pParent=0x8061018, rLstParents=std::deque with 52325 elements = {...})
    at /home/zzuf/pdf-fuzz/podofo-0.9.5/src/doc/PdfPagesTree.cpp:423
#12 0xb7eddc8b in PoDoFo::PdfPagesTree::GetPageNode (this=0x8062540, nPageNum=134615064, pParent=0x8061018, rLstParents=std::deque with 52325 elements = {...})
    at /home/zzuf/pdf-fuzz/podofo-0.9.5/src/doc/PdfPagesTree.cpp:423
#13 0xb7eddc8b in PoDoFo::PdfPagesTree::GetPageNode (this=0x8062540, nPageNum=134615064, pParent=0x8061018, rLstParents=std::deque with 52325 elements = {...})
    at /home/zzuf/pdf-fuzz/podofo-0.9.5/src/doc/PdfPagesTree.cpp:423
#14 0xb7eddc8b in PoDoFo::PdfPagesTree::GetPageNode (this=0x8062540, nPageNum=134615064, pParent=0x8061018, rLstParents=std::deque with 52325 elements = {...})
    at /home/zzuf/pdf-fuzz/podofo-0.9.5/src/doc/PdfPagesTree.cpp:423
#15 0xb7eddc8b in PoDoFo::PdfPagesTree::GetPageNode (this=0x8062540, nPageNum=134615064, pParent=0x8061018, rLstParents=std::deque with 52325 elements = {...})
    at /home/zzuf/pdf-fuzz/podofo-0.9.5/src/doc/PdfPagesTree.cpp:423
#16 0xb7eddc8b in PoDoFo::PdfPagesTree::GetPageNode (this=0x8062540, nPageNum=134615064, pParent=0x8061018, rLstParents=std::deque with 52325 elements = {...})
    at /home/zzuf/pdf-fuzz/podofo-0.9.5/src/doc/PdfPagesTree.cpp:423
#17 0xb7eddc8b in PoDoFo::PdfPagesTree::GetPageNode (this=0x8062540, nPageNum=134615064, pParent=0x8061018, rLstParents=std::deque with 52325 elements = {...})
    at /home/zzuf/pdf-fuzz/podofo-0.9.5/src/doc/PdfPagesTree.cpp:423
#18 0xb7eddc8b in PoDoFo::PdfPagesTree::GetPageNode (this=0x8062540, nPageNum=134615064, pParent=0x8061018, rLstParents=std::deque with 52325 elements = {...})
    at /home/zzuf/pdf-fuzz/podofo-0.9.5/src/doc/PdfPagesTree.cpp:423
#19 0xb7eddc8b in PoDoFo::PdfPagesTree::GetPageNode (this=0x8062540, nPageNum=134615064, pParent=0x8061018, rLstParents=std::deque with 52325 elements = {...})
...


PdfPagesTree.cpp:312:

PdfObject* PdfPagesTree::GetPageNode( int nPageNum, PdfObject* pParent, 
                                      PdfObjectList & rLstParents ) 
{
   ...
        // We have to traverse the tree
        while( it != rKidsArray.end() ) 
        {
           ...
            else if( (*it).IsReference() ) 
            {
                PdfObject* pChild = GetRoot()->GetOwner()->GetObject( (*it).GetReference() );
                if (!pChild) 
                {
                    PdfError::LogMessage( eLogSeverity_Critical, "Requesting page index %i. Child not found: %s\n", 
                                          nPageNum, (*it).GetReference().ToString().c_str()); 
                    return NULL;
                }

                if( this->IsTypePages(pChild) ) 
                {
                    int childCount = GetChildCount( pChild );
                    if( childCount < nPageNum + 1 ) // Pages are 0 based, but count is not
                    {
                        // skip this page node
                        // and go to the next one
                        nPageNum -= childCount;
                    }
                    else
                    {
                        rLstParents.push_back( pParent );
                        return this->GetPageNode( nPageNum, pChild, rLstParents );  //?????????????????????????????????
                    }
                }
                else if( this->IsTypePage(pChild) ) 
                {
                    if( 0 == nPageNum )
                    {
                        rLstParents.push_back( pParent );
                        return pChild;
                    } 

                    // Skip a normal page
                    if(nPageNum > 0 )
                        nPageNum--;
                }
		else
		{
                    const PdfReference & rLogRef = pChild->Reference();
                    pdf_objnum nLogObjNum = rLogRef.ObjectNumber();
                    pdf_gennum nLogGenNum = rLogRef.GenerationNumber();
		    PdfError::LogMessage( eLogSeverity_Critical,
                                          "Requesting page index %i. "
                        "Invalid datatype referenced in kids array: %s\n"
                        "Reference to invalid object: %i %i R\n", nPageNum,
                        pChild->GetDataTypeString(), nLogObjNum, nLogGenNum);
                }
            }
            else
            {
                PdfError::LogMessage( eLogSeverity_Critical, "Requesting page index %i. Invalid datatype in kids array: %s\n", 
                                      nPageNum, (*it).GetDataTypeString()); 
                return NULL;
            }
            
            ++it;
        }
    }

    return NULL;
}


How reproducible:

use podofomerge to read the attached poc file.

Steps to Reproduce:
1. podofomerge crash.pdf crash.pdf out.pdf