2
1
mirror of https://github.com/qpdf/qpdf.git synced 2025-01-03 15:17:29 +00:00

Protect against coding error of re-entrant parsing

This commit is contained in:
Jay Berkenbilt 2019-08-21 12:50:36 -04:00
parent ae5bd7102d
commit 225cd9dac2
3 changed files with 47 additions and 1 deletions

View File

@ -657,6 +657,31 @@ class QPDF
}; };
friend class Warner; friend class Warner;
// ParseGuard class allows QPDFObjectHandle to detect re-entrant
// resolution
class ParseGuard
{
friend class QPDFObjectHandle;
private:
ParseGuard(QPDF* qpdf) :
qpdf(qpdf)
{
if (qpdf)
{
qpdf->inParse(true);
}
}
~ParseGuard()
{
if (qpdf)
{
qpdf->inParse(false);
}
}
QPDF* qpdf;
};
friend class ParseGuard;
// Pipe class is restricted to QPDF_Stream // Pipe class is restricted to QPDF_Stream
class Pipe class Pipe
{ {
@ -816,6 +841,7 @@ class QPDF
friend class ResolveRecorder; friend class ResolveRecorder;
void parse(char const* password); void parse(char const* password);
void inParse(bool);
void warn(QPDFExc const& e); void warn(QPDFExc const& e);
void setTrailer(QPDFObjectHandle obj); void setTrailer(QPDFObjectHandle obj);
void read_xref(qpdf_offset_t offset); void read_xref(qpdf_offset_t offset);
@ -1352,6 +1378,7 @@ class QPDF
bool reconstructed_xref; bool reconstructed_xref;
bool fixed_dangling_refs; bool fixed_dangling_refs;
bool immediate_copy_from; bool immediate_copy_from;
bool in_parse;
// Linearization data // Linearization data
qpdf_offset_t first_xref_item_offset; // actual value from file qpdf_offset_t first_xref_item_offset; // actual value from file

View File

@ -150,6 +150,7 @@ QPDF::Members::Members() :
reconstructed_xref(false), reconstructed_xref(false),
fixed_dangling_refs(false), fixed_dangling_refs(false),
immediate_copy_from(false), immediate_copy_from(false),
in_parse(false),
first_xref_item_offset(0), first_xref_item_offset(0),
uncompressed_after_compressed(false) uncompressed_after_compressed(false)
{ {
@ -416,6 +417,20 @@ QPDF::parse(char const* password)
findAttachmentStreams(); findAttachmentStreams();
} }
void
QPDF::inParse(bool v)
{
if (this->m->in_parse == v)
{
// This happens of QPDFObjectHandle::parseInternal tries to
// resolve an indirect object while it is parsing.
throw std::logic_error(
"QPDF: re-entrant parsing detected. This is a qpdf bug."
" Please report at https://github.com/qpdf/qpdf/issues.");
}
this->m->in_parse = v;
}
void void
QPDF::warn(QPDFExc const& e) QPDF::warn(QPDFExc const& e)
{ {

View File

@ -1714,7 +1714,11 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
// This method must take care not to resolve any objects. Don't // This method must take care not to resolve any objects. Don't
// check the type of any object without first ensuring that it is // check the type of any object without first ensuring that it is
// a direct object. Otherwise, doing so may have the side effect // a direct object. Otherwise, doing so may have the side effect
// of reading the object and changing the file pointer. // of reading the object and changing the file pointer. If you do
// this, it will cause a logic error to be thrown from
// QPDF::inParse().
QPDF::ParseGuard pg(context);
empty = false; empty = false;