File poppler-CVE-2022-37052.patch of Package poppler.34109
Index: poppler-0.62.0/poppler/PDFDoc.cc
===================================================================
--- poppler-0.62.0.orig/poppler/PDFDoc.cc
+++ poppler-0.62.0/poppler/PDFDoc.cc
@@ -813,7 +813,14 @@ int PDFDoc::savePageAs(GooString *name,
Object resourcesObj = pagesDict->lookup("Resources");
if (resourcesObj.isDict())
markPageObjects(resourcesObj.getDict(), yRef, countRef, 0, refPage->num, rootNum + 2);
- markPageObjects(catDict, yRef, countRef, 0, refPage->num, rootNum + 2);
+ if (!markPageObjects(catDict, yRef, countRef, 0, refPage->num, rootNum + 2)) {
+ fclose(f);
+ delete yRef;
+ delete countRef;
+ delete outStr;
+ error(errSyntaxError, -1, "markPageObjects failed");
+ return errDamaged;
+ }
Dict *pageDict = page.getDict();
if (resourcesObj.isNull() && !pageDict->hasKey("Resources")) {
@@ -1514,7 +1521,7 @@ void PDFDoc::writeHeader(OutStream *outS
outStr->printf("%%\xE2\xE3\xCF\xD3\n");
}
-void PDFDoc::markDictionnary (Dict* dict, XRef * xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum, std::set<Dict*> *alreadyMarkedDicts)
+bool PDFDoc::markDictionnary (Dict* dict, XRef * xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum, std::set<Dict*> *alreadyMarkedDicts)
{
bool deleteSet = false;
if (!alreadyMarkedDicts) {
@@ -1525,7 +1532,7 @@ void PDFDoc::markDictionnary (Dict* dict
if (alreadyMarkedDicts->find(dict) != alreadyMarkedDicts->end()) {
error(errSyntaxWarning, -1, "PDFDoc::markDictionnary: Found recursive dicts");
if (deleteSet) delete alreadyMarkedDicts;
- return;
+ return true;
} else {
alreadyMarkedDicts->insert(dict);
}
@@ -1535,7 +1542,10 @@ void PDFDoc::markDictionnary (Dict* dict
const char *key = dict->getKey(i);
if (strcmp(key, "Annots") != 0) {
Object obj1 = dict->getValNF(i);
- markObject(&obj1, xRef, countRef, numOffset, oldRefNum, newRefNum, alreadyMarkedDicts);
+ const bool success = markObject(&obj1, xRef, countRef, numOffset, oldRefNum, newRefNum, alreadyMarkedDicts);
+ if (unlikely(!success)) {
+ return false;
+ }
} else {
Object annotsObj = dict->getValNF(i);
if (!annotsObj.isNull()) {
@@ -1547,9 +1557,11 @@ void PDFDoc::markDictionnary (Dict* dict
if (deleteSet) {
delete alreadyMarkedDicts;
}
+
+ return true;
}
-void PDFDoc::markObject (Object* obj, XRef *xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum, std::set<Dict*> *alreadyMarkedDicts)
+bool PDFDoc::markObject (Object* obj, XRef *xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum, std::set<Dict*> *alreadyMarkedDicts)
{
Array *array;
@@ -1558,25 +1570,39 @@ void PDFDoc::markObject (Object* obj, XR
array = obj->getArray();
for (int i=0; i<array->getLength(); i++) {
Object obj1 = array->getNF(i);
- markObject(&obj1, xRef, countRef, numOffset, oldRefNum, newRefNum, alreadyMarkedDicts);
+ const bool success = markObject(&obj1, xRef, countRef, numOffset, oldRefNum, newRefNum, alreadyMarkedDicts);
+ if (unlikely(!success)) {
+ return false;
+ }
}
break;
case objDict:
- markDictionnary (obj->getDict(), xRef, countRef, numOffset, oldRefNum, newRefNum, alreadyMarkedDicts);
+ {
+ const bool success = markDictionnary (obj->getDict(), xRef, countRef, numOffset, oldRefNum, newRefNum, alreadyMarkedDicts);
+ if (unlikely(!success)) {
+ return false;
+ }
+ }
break;
case objStream:
{
Stream *stream = obj->getStream();
- markDictionnary (stream->getDict(), xRef, countRef, numOffset, oldRefNum, newRefNum, alreadyMarkedDicts);
+ const bool success = markDictionnary (stream->getDict(), xRef, countRef, numOffset, oldRefNum, newRefNum, alreadyMarkedDicts);
+ if (unlikely(!success)) {
+ return false;
+ }
}
break;
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) {
- return; // already marked as free => should be replaced
+ return false; // already marked as free => should be replaced
+ }
+ const bool success = xRef->add(obj->getRef().num + numOffset, obj->getRef().gen, 0, gTrue);
+ if (unlikely(!success)) {
+ return false;
}
- xRef->add(obj->getRef().num + numOffset, obj->getRef().gen, 0, gTrue);
if (getXRef()->getEntry(obj->getRef().num)->type == xrefEntryCompressed) {
xRef->getEntry(obj->getRef().num + numOffset)->type = xrefEntryCompressed;
}
@@ -1592,12 +1618,17 @@ void PDFDoc::markObject (Object* obj, XR
break;
}
Object obj1 = getXRef()->fetch(obj->getRef().num, obj->getRef().gen);
- markObject(&obj1, xRef, countRef, numOffset, oldRefNum, newRefNum);
+ const bool success = markObject(&obj1, xRef, countRef, numOffset, oldRefNum, newRefNum);
+ if (unlikely(!success)) {
+ return false;
+ }
}
break;
default:
break;
}
+
+ return true;
}
void PDFDoc::replacePageDict(int pageNo, int rotate,
@@ -1640,7 +1671,7 @@ void PDFDoc::replacePageDict(int pageNo,
getXRef()->setModifiedObject(&page, *refPage);
}
-void PDFDoc::markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum, std::set<Dict*> *alreadyMarkedDicts)
+bool PDFDoc::markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum, std::set<Dict*> *alreadyMarkedDicts)
{
pageDict->remove("OpenAction");
pageDict->remove("Outlines");
@@ -1655,9 +1686,13 @@ void PDFDoc::markPageObjects(Dict *pageD
strcmp(key, "Annots") != 0 &&
strcmp(key, "P") != 0 &&
strcmp(key, "Root") != 0) {
- markObject(&value, xRef, countRef, numOffset, oldRefNum, newRefNum, alreadyMarkedDicts);
+ const bool success = markObject(&value, xRef, countRef, numOffset, oldRefNum, newRefNum, alreadyMarkedDicts);
+ if (unlikely(!success)) {
+ return false;
+ }
}
}
+ return true;
}
GBool PDFDoc::markAnnotations(Object *annotsObj, XRef *xRef, XRef *countRef, Guint numOffset, int oldPageNum, int newPageNum, std::set<Dict*> *alreadyMarkedDicts) {
Index: poppler-0.62.0/poppler/PDFDoc.h
===================================================================
--- poppler-0.62.0.orig/poppler/PDFDoc.h
+++ poppler-0.62.0/poppler/PDFDoc.h
@@ -292,7 +292,7 @@ public:
// rewrite pageDict with MediaBox, CropBox and new page CTM
void replacePageDict(int pageNo, int rotate, PDFRectangle *mediaBox, PDFRectangle *cropBox);
- void markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum, std::set<Dict*> *alreadyMarkedDicts = nullptr);
+ bool markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum, std::set<Dict*> *alreadyMarkedDicts = nullptr);
GBool markAnnotations(Object *annots, XRef *xRef, XRef *countRef, Guint numOffset, int oldPageNum, int newPageNum, std::set<Dict*> *alreadyMarkedDicts = nullptr);
void markAcroForm(Object *acrpForm, XRef *xRef, XRef *countRef, Guint numOffset, int oldPageNum, int newPageNum);
// write all objects used by pageDict to outStr
@@ -310,8 +310,8 @@ public:
private:
// insert referenced objects in XRef
- void markDictionnary (Dict* dict, XRef *xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum, std::set<Dict*> *alreadyMarkedDicts);
- void markObject (Object *obj, XRef *xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum, std::set<Dict*> *alreadyMarkedDicts = nullptr);
+ bool markDictionnary (Dict* dict, XRef *xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum, std::set<Dict*> *alreadyMarkedDicts);
+ bool markObject (Object *obj, XRef *xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum, std::set<Dict*> *alreadyMarkedDicts = nullptr);
static void writeDictionnary (Dict* dict, OutStream* outStr, XRef *xRef, Guint numOffset, Guchar *fileKey,
CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen, std::set<Dict*> *alreadyWrittenDicts);
Index: poppler-0.62.0/poppler/XRef.cc
===================================================================
--- poppler-0.62.0.orig/poppler/XRef.cc
+++ poppler-0.62.0/poppler/XRef.cc
@@ -1324,11 +1324,16 @@ int XRef::getNumEntry(Goffset offset)
else return -1;
}
-void XRef::add(int num, int gen, Goffset offs, GBool used) {
+bool XRef::add(int num, int gen, Goffset offs, GBool used) {
xrefLocker();
if (num >= size) {
if (num >= capacity) {
- entries = (XRefEntry *)greallocn(entries, num + 1, sizeof(XRefEntry));
+ entries = (XRefEntry *)greallocn_checkoverflow(entries, num + 1, sizeof(XRefEntry));
+ if (unlikely(entries == nullptr)) {
+ size = 0;
+ capacity = 0;
+ return false;
+ }
capacity = num + 1;
}
for (int i = size; i < num + 1; ++i) {
@@ -1351,6 +1356,7 @@ void XRef::add(int num, int gen, Goffset
e->type = xrefEntryFree;
e->offset = 0;
}
+ return true;
}
void XRef::setModifiedObject (Object* o, Ref r) {
Index: poppler-0.62.0/poppler/XRef.h
===================================================================
--- poppler-0.62.0.orig/poppler/XRef.h
+++ poppler-0.62.0/poppler/XRef.h
@@ -193,7 +193,7 @@ public:
void setModifiedObject(Object* o, Ref r);
Ref addIndirectObject (Object* o);
void removeIndirectObject(Ref r);
- void add(int num, int gen, Goffset offs, GBool used);
+ bool add(int num, int gen, Goffset offs, GBool used);
// Output XRef table to stream
void writeTableToFile(OutStream* outStr, GBool writeAllEntries);