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:
parent
ae5bd7102d
commit
225cd9dac2
@ -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
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user