Segmentation fault at src/doc/PdfDocument.cpp:179 (caused by...
A PDF parsing, modification and creation library.
Brought to you by:
domseichter
Hi, there is a NULL dereference bug which crashes at src/doc/PdfDocument.cpp:179.
//src/doc/PdfDocument.cpp
177 int PdfDocument::GetPageCount() const
178 {
179 return m_pPagesTree->GetTotalNumberOfPages();
180 }
This is caused by it's caller function PdfTranslator::setSource located at tools/podofoimpose/pdftranslator.cpp.
In that class, it defines a variable sourceDoc, but when it using sourceDoc, it doesn't do a new operation. Therefore it makes sourceDoc to be NULL.
for ( std::vector<std::string>::const_iterator ms = multiSource.begin(); ms != multiSource.end(); ++ms )
{
if ( ms == multiSource.begin() )
{
// std::cerr << "First doc is "<< (*ms).c_str() << endl;
try{
sourceDoc = new PdfMemDocument ( ( *ms ).c_str() );
}
catch(PdfError& e)
{
std::cerr << "Unable to create Document: " << PdfError::ErrorMessage( e.GetError() ) << std::endl;
return;
}
}
else
{
PdfMemDocument mdoc ( ( *ms ).c_str() );
// std::cerr << "Appending "<< mdoc.GetPageCount() << " page(s) of " << *ms << endl;
sourceDoc->InsertPages ( mdoc, 0, mdoc.GetPageCount() );
}
}
147 pcount = sourceDoc->GetPageCount(); **//Bug is here**
The gdb traceback is as follows.
─
gef➤ c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x00000000006ad069 in PoDoFo::PdfDocument::GetPageCount (this=0x0) at /home/lt/vuln-fuzz/program/podofo-r1974/src/doc/PdfDocument.cpp:179
179 return m_pPagesTree->GetTotalNumberOfPages();
Python Exception <class 'gdb.error'> There is no member named _M_dataplus.:
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x70
$rbx : 0x00007fffffffe000 → 0x0000000000000000
$rcx : 0x0
$rdx : 0x0
$rsp : 0x00007fffffffd9a0 → 0x0000000000000070 ("p"?)
$rbp : 0x00007fffffffd9b0 → 0x00007fffffffe350 → 0x00007fffffffe430 → 0x00000000008994b0 → <__libc_csu_init+0> push r15
$rsi : 0x00000ffffffffbaa → 0x0000000000000000
$rdi : 0x70
$rip : 0x00000000006ad069 → <PoDoFo::PdfDocument::GetPageCount()+0> mov rdi, QWORD PTR [rax]
$r8 : 0x00007ffff6110770 → 0x0000000000000000
$r9 : 0x00007ffff7fdb780 → 0x00007ffff7fdb780 → [loop detected]
$r10 : 0x1
$r11 : 0x246
$r12 : 0x00007fffffffddd0 → 0x00007fffffffdf28 → 0x00007ffff5d4ffb8 → 0x000d002200000853
$r13 : 0x00007fffffffdfb0 → 0x000010007edf3858 → 0x0000000000000000
$r14 : 0x00007fffffffdd90 → 0x0000000000000000
$r15 : 0x00007fffffffddb0 → 0x00007fffffffdf00 → 0x0000000000c11280 → 0x00007ffff6fd5988 → 0x00007ffff6d69b70 → <std::basic_ostream<char,+0> mov rax, QWORD PTR [rip+0x26d7e9] # 0x7ffff6fd7360
$eflags: [carry PARITY adjust ZERO sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffd9a0│+0x0000: 0x0000000000000070 ("p"?) ← $rsp
0x00007fffffffd9a8│+0x0008: 0x0000000000000000
0x00007fffffffd9b0│+0x0010: 0x00007fffffffe350 → 0x00007fffffffe430 → 0x00000000008994b0 → <__libc_csu_init+0> push r15 ← $rbp
0x00007fffffffd9b8│+0x0018: 0x00000000005dfe97 → <PoDoFo::Impose::PdfTranslator::setSource(std::__cxx11::basic_string<char,+0> mov rcx, QWORD PTR [rbx+0x218]
0x00007fffffffd9c0│+0x0020: 0x0000000041b58ab3
0x00007fffffffd9c8│+0x0028: 0x00000000008c0db5 → "13 32 32 7 agg.tmp 96 520 2 in 752 32 7 ref.tmp 81[...]"
0x00007fffffffd9d0│+0x0030: 0x00000000005df200 → <PoDoFo::Impose::PdfTranslator::setSource(std::__cxx11::basic_string<char,+0> push rbp
0x00007fffffffd9d8│+0x0038: 0x00007ffff7e85cd0 → 0x0000000000000000
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x6ad05c <PoDoFo::PdfDocument::GetPageCount()+0> mov rdi, QWORD PTR [rbp-0x10]
0x6ad060 <PoDoFo::PdfDocument::GetPageCount()+0> call 0x5aa570 <__asan::__asan_report_load8(__sanitizer::uptr)>
0x6ad065 <PoDoFo::PdfDocument::GetPageCount()+0> mov rax, QWORD PTR [rbp-0x10]
→ 0x6ad069 <PoDoFo::PdfDocument::GetPageCount()+0> mov rdi, QWORD PTR [rax]
0x6ad06c <PoDoFo::PdfDocument::GetPageCount()+0> call 0x72f8c0 <PoDoFo::PdfPagesTree::GetTotalNumberOfPages() const>
0x6ad071 <PoDoFo::PdfDocument::GetPageCount()+0> add rsp, 0x10
0x6ad075 <PoDoFo::PdfDocument::GetPageCount()+0> pop rbp
0x6ad076 <PoDoFo::PdfDocument::GetPageCount()+0> ret
0x6ad077 nop WORD PTR [rax+rax*1+0x0]
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── source:/home/lt/vuln-f[...].cpp+179 ────
174 return m_pCatalog->GetIndirectKey( PdfName( pszName ) );
175 }
176
177 int PdfDocument::GetPageCount() const
178 {
→ 179 return m_pPagesTree->GetTotalNumberOfPages();
180 }
181
182 PdfPage* PdfDocument::GetPage( int nIndex ) const
183 {
184 if( nIndex < 0 || nIndex >= m_pPagesTree->GetTotalNumberOfPages() )
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "podofoimpose", stopped, reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x6ad069 → PoDoFo::PdfDocument::GetPageCount(this=0x0)
[#1] 0x5dfe97 → PoDoFo::Impose::PdfTranslator::setSource(this=0x617000000080, source=)
[#2] 0x5de061 → main(argc=0x4, argv=0x7fffffffe518)
cmd: ./podofoimpose ./poc output native
This happens when multiSource is empty at the for loop before. I've implemented a fix awaiting my tests.
The fix for this segfault is now committed in svn r1991, leaving this "pending" for corroboration of its correctness, especially Windows users are invited to test, as I'm no user of it (anymore), but also everyone else.
Let's close this, to avoid forever-pending issues.