diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc index f052772..de23d19 100644 --- a/poppler/PDFDoc.cc +++ b/poppler/PDFDoc.cc @@ -1501,7 +1501,7 @@ void PDFDoc::markObject (Object* obj, XRef *xRef, XRef *countRef, Guint numOffse case objRef: { if (obj->getRef().num + (int) numOffset >= xRef->getNumObjects() || xRef->getEntry(obj->getRef().num + numOffset)->type == xrefEntryFree) { - if (getXRef()->getEntry(obj->getRef().num)->type == xrefEntryFree) { + if (getXRef()->getEntryAndReconstruct(obj->getRef().num)->type == xrefEntryFree) { return; // already marked as free => should be replaced } xRef->add(obj->getRef().num + numOffset, obj->getRef().gen, 0, gTrue); diff --git a/poppler/XRef.cc b/poppler/XRef.cc index 1bbbdc5..f89d0e2 100644 --- a/poppler/XRef.cc +++ b/poppler/XRef.cc @@ -1639,6 +1639,52 @@ XRefEntry *XRef::getEntry(int i, GBool complainIfMissing) return &entries[i]; } +XRefEntry *XRef::getEntryAndReconstruct(int i, GBool complainIfMissing) +{ + if (i >= size || entries[i].type == xrefEntryNone) { + + if ((!xRefStream) && mainXRefEntriesOffset) { + if (!parseEntry(mainXRefEntriesOffset + 20*i, &entries[i])) { + error(errSyntaxError, -1, "Failed to parse XRef entry [{0:d}].", i); + } + } else { + // Read XRef tables until the entry we're looking for is found + readXRefUntil(i); + + // We might have reconstructed the xref + // Check again i is in bounds + if (unlikely(i >= size)) { + static XRefEntry dummy; + dummy.offset = 0; + dummy.gen = -1; + dummy.type = xrefEntryNone; + dummy.flags = 0; + return &dummy; + } + + if (!xRefStream && entries[i].type == xrefEntryNone) { + GBool wasReconstructed = false; + if (!(ok = constructXRef(&wasReconstructed))) { + errCode = errDamaged; + } else { + for (int j=0; j < size; j++) { + if (entries[j].type == xrefEntryNone) { + entries[j].type = xrefEntryFree; + } + } + } + } + if (entries[i].type == xrefEntryFree) { + if (complainIfMissing) { + error(errSyntaxError, -1, "Invalid XRef entry"); + } + } + } + } + + return &entries[i]; +} + // Recursively sets the Unencrypted flag in all referenced xref entries void XRef::markUnencrypted(Object *obj) { Object obj1; diff --git a/poppler/XRef.h b/poppler/XRef.h index 70065d8..75b7e2e 100644 --- a/poppler/XRef.h +++ b/poppler/XRef.h @@ -173,6 +173,7 @@ public: // Direct access. XRefEntry *getEntry(int i, GBool complainIfMissing = gTrue); + XRefEntry *getEntryAndReconstruct(int i, GBool complainIfMissing = gTrue); Object *getTrailerDict() { return &trailerDict; } // Write access