You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
==28751==ERROR: AddressSanitizer: heap-use-after-free on address 0x6070000076c5 at pc 0x0000008799bc bp 0x7fffffff6a30 sp 0x7fffffff6a28
WRITE of size 1 at 0x6070000076c5 thread T0
#0 0x8799bb in Pl_ASCII85Decoder::write(unsigned char*, unsigned long) /src/qpdf/libqpdf/Pl_ASCII85Decoder.cc:85:32
#1 0x877725 in Pl_AES_PDF::flush(bool) /src/qpdf/libqpdf/Pl_AES_PDF.cc:241:16
#2 0x877c75 in Pl_AES_PDF::finish() /src/qpdf/libqpdf/Pl_AES_PDF.cc
#3 0x5996ab in QPDF::pipeStreamData(PointerHolder<QPDF::EncryptionParameters>, PointerHolder<InputSource>, QPDF&, int, int, long long, unsigned long, QPDFObjectHandle, bool, Pipeline*, bool, bool) /src/qpdf/libqpdf/QPDF.cc:2899:23
#4 0x599c9d in QPDF::pipeStreamData(int, int, long long, unsigned long, QPDFObjectHandle, Pipeline*, bool, bool) /src/qpdf/libqpdf/QPDF.cc:2920:12
#5 0x77e4c7 in QPDF::Pipe::pipeStreamData(QPDF*, int, int, long long, unsigned long, QPDFObjectHandle, Pipeline*, bool, bool) /src/qpdf/include/qpdf/QPDF.hh:718:19
#6 0x76e02e in QPDF_Stream::pipeStreamData(Pipeline*, bool*, int, qpdf_stream_decode_level_e, bool, bool) /src/qpdf/libqpdf/QPDF_Stream.cc:700:8
#7 0x637e27 in QPDFObjectHandle::pipeStreamData(Pipeline*, int, qpdf_stream_decode_level_e, bool, bool) /src/qpdf/libqpdf/QPDFObjectHandle.cc:1228:51
#8 0x700fbf in QPDFWriter::unparseObject(QPDFObjectHandle, int, int, unsigned long, bool) /src/qpdf/libqpdf/QPDFWriter.cc:1826:24
#9 0x71f286 in QPDFWriter::writeObject(QPDFObjectHandle, int) /src/qpdf/libqpdf/QPDFWriter.cc:2169:2
#10 0x737528 in QPDFWriter::writeStandard() /src/qpdf/libqpdf/QPDFWriter.cc:3676:2
#11 0x72aae7 in QPDFWriter::write() /src/qpdf/libqpdf/QPDFWriter.cc:2745:2
#12 0x51bb07 in FuzzHelper::doWrite(PointerHolder<QPDFWriter>) /src/qpdf_afl_fuzzer.cc:68:12
#13 0x51cb03 in FuzzHelper::testWrite() /src/qpdf_afl_fuzzer.cc:92:5
#14 0x5219a6 in FuzzHelper::doChecks() /src/qpdf_afl_fuzzer.cc:194:5
#15 0x5219a6 in FuzzHelper::run() /src/qpdf_afl_fuzzer.cc:210
#16 0x5221b7 in main /src/qpdf_afl_fuzzer.cc:228:7
#17 0x7ffff6a99bf6 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)
#18 0x41eb89 in _start (/src/qpdf_afl_fuzzer+0x41eb89)
0x6070000076c5 is located 21 bytes inside of 78-byte region [0x6070000076b0,0x6070000076fe)
freed by thread T0 here:
#0 0x517d68 in operator delete(void*) (/src/qpdf_afl_fuzzer+0x517d68)
#1 0x7ffff7af21a9 in std::runtime_error::~runtime_error() (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xa81a9)
#2 0x599c9d in QPDF::pipeStreamData(int, int, long long, unsigned long, QPDFObjectHandle, Pipeline*, bool, bool) /src/qpdf/libqpdf/QPDF.cc:2920:12
#3 0x77e4c7 in QPDF::Pipe::pipeStreamData(QPDF*, int, int, long long, unsigned long, QPDFObjectHandle, Pipeline*, bool, bool) /src/qpdf/include/qpdf/QPDF.hh:718:19
#4 0x76e02e in QPDF_Stream::pipeStreamData(Pipeline*, bool*, int, qpdf_stream_decode_level_e, bool, bool) /src/qpdf/libqpdf/QPDF_Stream.cc:700:8
#5 0x637e27 in QPDFObjectHandle::pipeStreamData(Pipeline*, int, qpdf_stream_decode_level_e, bool, bool) /src/qpdf/libqpdf/QPDFObjectHandle.cc:1228:51
#6 0x700fbf in QPDFWriter::unparseObject(QPDFObjectHandle, int, int, unsigned long, bool) /src/qpdf/libqpdf/QPDFWriter.cc:1826:24
#7 0x71f286 in QPDFWriter::writeObject(QPDFObjectHandle, int) /src/qpdf/libqpdf/QPDFWriter.cc:2169:2
#8 0x737528 in QPDFWriter::writeStandard() /src/qpdf/libqpdf/QPDFWriter.cc:3676:2
#9 0x72aae7 in QPDFWriter::write() /src/qpdf/libqpdf/QPDFWriter.cc:2745:2
#10 0x51bb07 in FuzzHelper::doWrite(PointerHolder<QPDFWriter>) /src/qpdf_afl_fuzzer.cc:68:12
#11 0x5219a6 in FuzzHelper::doChecks() /src/qpdf_afl_fuzzer.cc:194:5
#12 0x5219a6 in FuzzHelper::run() /src/qpdf_afl_fuzzer.cc:210
#13 0x7ffff6a99bf6 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21bf6)
previously allocated by thread T0 here:
#0 0x516ff0 in operator new(unsigned long) (/src/qpdf_afl_fuzzer+0x516ff0)
#1 0x7ffff7b1dc28 in std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xd3c28)
#2 0x883ce8 in Pl_Flate::handleData(unsigned char*, unsigned long, int) /src/qpdf/libqpdf/Pl_Flate.cc:197:12
#3 0x8833d5 in Pl_Flate::write(unsigned char*, unsigned long) /src/qpdf/libqpdf/Pl_Flate.cc:92:9
#4 0x87a0a7 in Pl_ASCII85Decoder::flush() /src/qpdf/libqpdf/Pl_ASCII85Decoder.cc:122:16
#5 0x87997b in Pl_ASCII85Decoder::write(unsigned char*, unsigned long) /src/qpdf/libqpdf/Pl_ASCII85Decoder.cc:88:4
#6 0x877725 in Pl_AES_PDF::flush(bool) /src/qpdf/libqpdf/Pl_AES_PDF.cc:241:16
SUMMARY: AddressSanitizer: heap-use-after-free /src/qpdf/libqpdf/Pl_ASCII85Decoder.cc:85:32 in Pl_ASCII85Decoder::write(unsigned char*, unsigned long)
Shadow bytes around the buggy address:
0x0c0e7fff8e80: fa fa fd fd fd fd fd fd fd fd fd fa fa fa fa fa
0x0c0e7fff8e90: 00 00 00 00 00 00 00 00 01 fa fa fa fa fa fd fd
0x0c0e7fff8ea0: fd fd fd fd fd fd fd fa fa fa fa fa fd fd fd fd
0x0c0e7fff8eb0: fd fd fd fd fd fd fa fa fa fa 00 00 00 00 00 00
0x0c0e7fff8ec0: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 00
=>0x0c0e7fff8ed0: 00 fa fa fa fa fa fd fd[fd]fd fd fd fd fd fd fd
0x0c0e7fff8ee0: fa fa fa fa fd fd fd fd fd fd fd fd fd fa fa fa
0x0c0e7fff8ef0: fa fa fd fd fd fd fd fd fd fd fd fa fa fa fa fa
0x0c0e7fff8f00: 00 00 00 00 00 00 00 00 01 fa fa fa fa fa fa fa
0x0c0e7fff8f10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0e7fff8f20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==28751==ABORTING
The test program is a wrapper that I modified based on oss-fuzz wrapper:
// file name is qpdf_afl_fuzzer.c#include<qpdf/QPDF.hh>#include<qpdf/QPDFWriter.hh>#include<qpdf/QUtil.hh>#include<qpdf/BufferInputSource.hh>#include<qpdf/Buffer.hh>#include<qpdf/Pl_Discard.hh>#include<qpdf/QPDFPageDocumentHelper.hh>#include<qpdf/QPDFPageObjectHelper.hh>#include<qpdf/QPDFPageLabelDocumentHelper.hh>#include<qpdf/QPDFOutlineDocumentHelper.hh>#include<qpdf/QPDFAcroFormDocumentHelper.hh>#include<cstdlib>classDiscardContents: publicQPDFObjectHandle::ParserCallbacks
{
public:
virtual ~DiscardContents() {}
virtualvoidhandleObject(QPDFObjectHandle) {}
virtualvoidhandleEOF() {}
};
classFuzzHelper
{
public:
FuzzHelper(char*data);
voidrun();
private:
PointerHolder<QPDF>getQpdf();
PointerHolder<QPDFWriter>getWriter(PointerHolder<QPDF>);
voiddoWrite(PointerHolder<QPDFWriter>w);
voidtestWrite();
voidtestPages();
voidtestOutlines();
voiddoChecks();
charconst*input_f;
Pl_Discarddiscard;
};
FuzzHelper::FuzzHelper(char*_input) :
// We do not modify data, so it is safe to remove the const for Bufferinput_f(_input)
{
}
PointerHolder<QPDF>FuzzHelper::getQpdf()
{
PointerHolder<QPDF>qpdf=newQPDF();
qpdf->processFile(input_f);
returnqpdf;
}
PointerHolder<QPDFWriter>FuzzHelper::getWriter(PointerHolder<QPDF>qpdf)
{
PointerHolder<QPDFWriter>w=newQPDFWriter(*qpdf);
w->setOutputPipeline(&this->discard);
w->setDecodeLevel(qpdf_dl_all);
returnw;
}
voidFuzzHelper::doWrite(PointerHolder<QPDFWriter>w)
{
try
{
w->write();
}
catch (QPDFExcconst&e)
{
std::cerr << e.what() << std::endl;
}
catch (std::runtime_errorconst&e)
{
std::cerr << e.what() << std::endl;
}
}
voidFuzzHelper::testWrite()
{
// Write in various ways to exercise QPDFWriterPointerHolder<QPDF>q;
PointerHolder<QPDFWriter>w;
q=getQpdf();
w=getWriter(q);
w->setDeterministicID(true);
w->setQDFMode(true);
doWrite(w);
q=getQpdf();
w=getWriter(q);
w->setStaticID(true);
w->setLinearization(true);
w->setR6EncryptionParameters(
"u", "o", true, true, true, true, true, true, qpdf_r3p_full, true);
doWrite(w);
q=getQpdf();
w=getWriter(q);
w->setStaticID(true);
w->setObjectStreamMode(qpdf_o_disable);
w->setR3EncryptionParameters(
"u", "o", true, true, qpdf_r3p_full, qpdf_r3m_all);
doWrite(w);
q=getQpdf();
w=getWriter(q);
w->setDeterministicID(true);
w->setObjectStreamMode(qpdf_o_generate);
w->setLinearization(true);
doWrite(w);
}
voidFuzzHelper::testPages()
{
// Parse all content streams, and exercise some helpers that// operate on pages.PointerHolder<QPDF>q=getQpdf();
QPDFPageDocumentHelperpdh(*q);
QPDFPageLabelDocumentHelperpldh(*q);
QPDFOutlineDocumentHelperodh(*q);
QPDFAcroFormDocumentHelperafdh(*q);
afdh.generateAppearancesIfNeeded();
pdh.flattenAnnotations();
std::vector<QPDFPageObjectHelper>pages=pdh.getAllPages();
DiscardContentsdiscard_contents;
intpageno=0;
for (std::vector<QPDFPageObjectHelper>::iteratoriter=pages.begin();
iter!=pages.end(); ++iter)
{
QPDFPageObjectHelper&page(*iter);
++pageno;
try
{
page.coalesceContentStreams();
page.parsePageContents(&discard_contents);
page.getPageImages();
pldh.getLabelForPage(pageno);
QPDFObjectHandlepage_obj(page.getObjectHandle());
page_obj.getJSON(true).unparse();
odh.getOutlinesForPage(page_obj.getObjGen());
std::vector<QPDFAnnotationObjectHelper>annotations=afdh.getWidgetAnnotationsForPage(page);
for (std::vector<QPDFAnnotationObjectHelper>::iteratorannot_iter=annotations.begin();
annot_iter!=annotations.end(); ++annot_iter)
{
QPDFAnnotationObjectHelper&aoh=*annot_iter;
afdh.getFieldForAnnotation(aoh);
}
}
catch (QPDFExc&e)
{
std::cerr << "page " << pageno << ": "
<< e.what() << std::endl;
}
}
}
voidFuzzHelper::testOutlines()
{
PointerHolder<QPDF>q=getQpdf();
std::list<std::vector<QPDFOutlineObjectHelper>>queue;
QPDFOutlineDocumentHelperodh(*q);
queue.push_back(odh.getTopLevelOutlines());
while (! queue.empty())
{
std::vector<QPDFOutlineObjectHelper>&outlines=*(queue.begin());
for (std::vector<QPDFOutlineObjectHelper>::iteratoriter=outlines.begin();
iter!=outlines.end(); ++iter)
{
QPDFOutlineObjectHelper&ol=*iter;
ol.getDestPage();
queue.push_back(ol.getKids());
}
queue.pop_front();
}
}
voidFuzzHelper::doChecks()
{
// Get as much coverage as possible in parts of the library that// might benefit from fuzzing.testWrite();
testPages();
testOutlines();
}
voidFuzzHelper::run()
{
// The goal here is that you should be able to throw anything at// libqpdf and it will respond without any memory errors and never// do anything worse than throwing a QPDFExc or// std::runtime_error. Throwing any other kind of exception,// segfaulting, or having a memory error (when built with// appropriate sanitizers) will all cause abnormal exit.try
{
doChecks();
}
catch (QPDFExcconst&e)
{
std::cerr << "QPDFExc: " << e.what() << std::endl;
}
catch (std::runtime_errorconst&e)
{
std::cerr << "runtime_error: " << e.what() << std::endl;
}
}
intmain(intargc, char**argv){
if (argc<2){
std::cerr << "Please input the processed file!\n";
}
FuzzHelperf(argv[1]);
f.run();
return0;
}
The log from ASAN:
The test program is a wrapper that I modified based on oss-fuzz wrapper:
The PoC file is attached:
poc.zip
The text was updated successfully, but these errors were encountered: