Add optional parameter allow_nullptr to QPDFObjectHandle::getOwningQPDF

Also, inline method and add optional parameter error_msg.
This commit is contained in:
m-holger 2022-08-06 19:52:07 +01:00
parent cef6425bca
commit c53d54b13d
8 changed files with 59 additions and 64 deletions

View File

@ -957,9 +957,11 @@ class QPDFObjectHandle
std::set<std::string>* resource_names = nullptr);
// Return the QPDF object that owns an indirect object. Returns
// null for a direct object.
// null for a direct object if allow_nullptr is set to true or
// throws a runtime error otherwise.
QPDF_DLL
QPDF* getOwningQPDF();
inline QPDF*
getOwningQPDF(bool allow_nullptr = true, std::string const& error_msg = "");
// Create a shallow copy of an object as a direct object, but do not
// traverse across indirect object boundaries. That means that,
@ -1876,4 +1878,17 @@ QPDFObjectHandle::isInitialized() const
return initialized;
}
// Indirect object accessors
inline QPDF*
QPDFObjectHandle::getOwningQPDF(
bool allow_nullptr, std::string const& error_msg)
{
// Will be null for direct objects
if (!allow_nullptr && (this->qpdf == nullptr)) {
throw std::runtime_error(
error_msg == "" ? "attempt to use a null qpdf object" : error_msg);
}
return this->qpdf;
}
#endif // QPDFOBJECTHANDLE_HH

View File

@ -2266,7 +2266,7 @@ QPDF::copyForeignObject(QPDFObjectHandle foreign)
throw std::logic_error(
"QPDF::copyForeign called with direct object handle");
}
QPDF* other = foreign.getOwningQPDF();
QPDF* other = foreign.getOwningQPDF(false);
if (other == this) {
QTC::TC("qpdf", "QPDF copyForeign not foreign");
throw std::logic_error(
@ -2456,11 +2456,9 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign)
QPDFObjGen local_og(result.getObjGen());
// Copy information from the foreign stream so we can pipe its
// data later without keeping the original QPDF object around.
QPDF* foreign_stream_qpdf = foreign.getOwningQPDF();
if (!foreign_stream_qpdf) {
throw std::logic_error("unable to retrieve owning qpdf"
" from foreign stream");
}
QPDF* foreign_stream_qpdf = foreign.getOwningQPDF(
false, "unable to retrieve owning qpdf from foreign stream");
QPDF_Stream* stream = dynamic_cast<QPDF_Stream*>(
QPDFObjectHandle::ObjAccessor::getObject(foreign).get());
if (!stream) {

View File

@ -362,13 +362,11 @@ QPDFFormFieldObjectHelper::setV(QPDFObjectHandle value, bool need_appearances)
setFieldAttribute("/V", value);
}
if (need_appearances) {
QPDF* qpdf = this->oh.getOwningQPDF();
if (!qpdf) {
throw std::logic_error(
"QPDFFormFieldObjectHelper::setV called with"
" need_appearances = true on an object that is"
" not associated with an owning QPDF");
}
QPDF* qpdf = this->oh.getOwningQPDF(
false,
"QPDFFormFieldObjectHelper::setV called with need_appearances = "
"true on an object that is not associated with an owning QPDF");
QPDFAcroFormDocumentHelper(*qpdf).setNeedAppearances(true);
}
}
@ -883,7 +881,7 @@ QPDFFormFieldObjectHelper::generateTextAppearance(
if (found_font_in_dr && resources.isDictionary()) {
QTC::TC("qpdf", "QPDFFormFieldObjectHelper get font from /DR");
if (resources.isIndirect()) {
resources = resources.getOwningQPDF()->makeIndirectObject(
resources = resources.getOwningQPDF(false)->makeIndirectObject(
resources.shallowCopy());
AS.getDict().replaceKey("/Resources", resources);
}

View File

@ -2161,7 +2161,7 @@ QPDFJob::doUnderOverlayForPage(
std::map<unsigned long long, std::shared_ptr<QPDFAcroFormDocumentHelper>>
afdh;
auto make_afdh = [&](QPDFPageObjectHelper& ph) {
QPDF* q = ph.getObjectHandle().getOwningQPDF();
QPDF* q = ph.getObjectHandle().getOwningQPDF(false);
return get_afdh_for_qpdf(afdh, q);
};
auto dest_afdh = make_afdh(dest_page);
@ -2597,7 +2597,7 @@ static QPDFObjectHandle
added_page(QPDF& pdf, QPDFObjectHandle page)
{
QPDFObjectHandle result = page;
if (page.getOwningQPDF() != &pdf) {
if (page.getOwningQPDF(false) != &pdf) {
// Calling copyForeignObject on an object we already copied
// will give us the already existing copy.
result = pdf.copyForeignObject(page);

View File

@ -1207,14 +1207,6 @@ QPDFObjectHandle::getUniqueResourceName(
" QPDFObjectHandle::getUniqueResourceName");
}
// Indirect object accessors
QPDF*
QPDFObjectHandle::getOwningQPDF()
{
// Will be null for direct objects
return this->qpdf;
}
// Dictionary mutators
void
@ -1634,16 +1626,15 @@ QPDFObjectHandle::coalesceContentStreams()
// files may have pages that are invalid in other ways.
return;
}
QPDF* qpdf = getOwningQPDF();
if (qpdf == nullptr) {
// Should not be possible for a page object to not have an
// owning PDF unless it was manually constructed in some
// incorrect way. However, it can happen in a PDF file whose
// page structure is direct, which is against spec but still
// possible to hand construct, as in fuzz issue 27393.
throw std::runtime_error("coalesceContentStreams called on object"
" with no associated PDF file");
}
// Should not be possible for a page object to not have an
// owning PDF unless it was manually constructed in some
// incorrect way. However, it can happen in a PDF file whose
// page structure is direct, which is against spec but still
// possible to hand construct, as in fuzz issue 27393.
QPDF* qpdf = getOwningQPDF(
false,
"coalesceContentStreams called on object with no associated PDF file");
QPDFObjectHandle new_contents = newStream(qpdf);
this->replaceKey("/Contents", new_contents);

View File

@ -432,7 +432,8 @@ QPDFPageObjectHelper::externalizeInlineImages(size_t min_size, bool shallow)
this->oh.replaceKey(
"/Contents",
QPDFObjectHandle::newStream(
this->oh.getOwningQPDF(), b.getBufferSharedPointer()));
this->oh.getOwningQPDF(false),
b.getBufferSharedPointer()));
}
}
} else {
@ -683,11 +684,10 @@ QPDFPageObjectHelper::removeUnreferencedResources()
QPDFPageObjectHelper
QPDFPageObjectHelper::shallowCopyPage()
{
QPDF* qpdf = this->oh.getOwningQPDF();
if (!qpdf) {
throw std::runtime_error("QPDFPageObjectHelper::shallowCopyPage"
" called with a direct object");
}
QPDF* qpdf = this->oh.getOwningQPDF(
false,
"QPDFPageObjectHelper::shallowCopyPage called with a direct object");
QPDFObjectHandle new_page = this->oh.shallowCopy();
return QPDFPageObjectHelper(qpdf->makeIndirectObject(new_page));
}
@ -743,11 +743,10 @@ QPDFPageObjectHelper::getMatrixForTransformations(bool invert)
QPDFObjectHandle
QPDFPageObjectHelper::getFormXObjectForPage(bool handle_transformations)
{
QPDF* qpdf = this->oh.getOwningQPDF();
if (!qpdf) {
throw std::runtime_error("QPDFPageObjectHelper::getFormXObjectForPage"
" called with a direct object");
}
QPDF* qpdf = this->oh.getOwningQPDF(
false,
"QPDFPageObjectHelper::getFormXObjectForPage called with a direct "
"object");
QPDFObjectHandle result = QPDFObjectHandle::newStream(qpdf);
QPDFObjectHandle newdict = result.getDict();
newdict.replaceKey("/Type", QPDFObjectHandle::newName("/XObject"));
@ -917,11 +916,9 @@ QPDFPageObjectHelper::placeFormXObject(
void
QPDFPageObjectHelper::flattenRotation(QPDFAcroFormDocumentHelper* afdh)
{
QPDF* qpdf = this->oh.getOwningQPDF();
if (!qpdf) {
throw std::runtime_error("QPDFPageObjectHelper::flattenRotation"
" called with a direct object");
}
QPDF* qpdf = this->oh.getOwningQPDF(
false,
"QPDFPageObjectHelper::flattenRotation called with a direct object");
auto rotate_oh = this->oh.getKey("/Rotate");
int rotate = 0;
@ -1066,16 +1063,12 @@ QPDFPageObjectHelper::copyAnnotations(
return;
}
QPDF* from_qpdf = from_page.getObjectHandle().getOwningQPDF();
if (!from_qpdf) {
throw std::runtime_error("QPDFPageObjectHelper::copyAnnotations:"
" from page is a direct object");
}
QPDF* this_qpdf = this->oh.getOwningQPDF();
if (!this_qpdf) {
throw std::runtime_error("QPDFPageObjectHelper::copyAnnotations:"
" this page is a direct object");
}
QPDF* from_qpdf = from_page.getObjectHandle().getOwningQPDF(
false,
"QPDFPageObjectHelper::copyAnnotations: from page is a direct object");
QPDF* this_qpdf = this->oh.getOwningQPDF(
false,
"QPDFPageObjectHelper::copyAnnotations: this page is a direct object");
std::vector<QPDFObjectHandle> new_annots;
std::vector<QPDFObjectHandle> new_fields;

View File

@ -234,7 +234,7 @@ QPDF::insertPage(QPDFObjectHandle newpage, int pos)
newpage = makeIndirectObject(newpage);
} else if (newpage.getOwningQPDF() != this) {
QTC::TC("qpdf", "QPDF insert foreign page");
newpage.getOwningQPDF()->pushInheritedAttributesToPage();
newpage.getOwningQPDF(false)->pushInheritedAttributesToPage();
newpage = copyForeignObject(newpage);
} else {
QTC::TC("qpdf", "QPDF insert indirect page");

View File

@ -1,8 +1,8 @@
#include <qpdf/QTC.hh>
#include <qpdf/QUtil.hh>
#include <set>
#include <map>
#include <set>
#include <stdio.h>
static bool