2
1
mirror of https://github.com/qpdf/qpdf.git synced 2025-01-03 07:12:28 +00:00

Merge pull request #747 from m-holger/new_stream

Add optional parameter allow_nullptr to QPDFObjectHandle::getOwningQPDF
This commit is contained in:
Jay Berkenbilt 2022-08-29 16:33:19 -04:00 committed by GitHub
commit 0adfd74f8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 58 additions and 63 deletions

View File

@ -957,9 +957,11 @@ class QPDFObjectHandle
std::set<std::string>* resource_names = nullptr); std::set<std::string>* resource_names = nullptr);
// Return the QPDF object that owns an indirect object. Returns // 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_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 // Create a shallow copy of an object as a direct object, but do not
// traverse across indirect object boundaries. That means that, // traverse across indirect object boundaries. That means that,
@ -1876,4 +1878,17 @@ QPDFObjectHandle::isInitialized() const
return initialized; 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 #endif // QPDFOBJECTHANDLE_HH

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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