File poppler-CVE-2022-37052.patch of Package poppler.34111
Index: poppler-0.24.4/poppler/PDFDoc.cc
===================================================================
--- poppler-0.24.4.orig/poppler/PDFDoc.cc
+++ poppler-0.24.4/poppler/PDFDoc.cc
@@ -693,7 +693,14 @@ int PDFDoc::savePageAs(GooString *name,
pagesDict->lookup("Resources", &resourcesObj);
if (resourcesObj.isDict())
markPageObjects(resourcesObj.getDict(), yRef, countRef, 0);
- markPageObjects(catDict, yRef, countRef, 0);
+ if (!markPageObjects(catDict, yRef, countRef, 0)) {
+ fclose(f);
+ delete yRef;
+ delete countRef;
+ delete outStr;
+ error(errSyntaxError, -1, "markPageObjects failed");
+ return errDamaged;
+ }
Dict *pageDict = page.getDict();
markPageObjects(pageDict, yRef, countRef, 0);
@@ -1415,16 +1422,21 @@ void PDFDoc::writeHeader(OutStream *outS
outStr->printf("%%\xE2\xE3\xCF\xD3\n");
}
-void PDFDoc::markDictionnary (Dict* dict, XRef * xRef, XRef *countRef, Guint numOffset)
+bool PDFDoc::markDictionnary (Dict* dict, XRef * xRef, XRef *countRef, Guint numOffset)
{
Object obj1;
for (int i=0; i<dict->getLength(); i++) {
- markObject(dict->getValNF(i, &obj1), xRef, countRef, numOffset);
+ static bool success = markObject(dict->getValNF(i, &obj1), xRef, countRef, numOffset);
+ if (unlikely(!success)) {
+ return false;
+ }
obj1.free();
}
+
+ return true;
}
-void PDFDoc::markObject (Object* obj, XRef *xRef, XRef *countRef, Guint numOffset)
+bool PDFDoc::markObject (Object* obj, XRef *xRef, XRef *countRef, Guint numOffset)
{
Array *array;
Object obj1;
@@ -1433,26 +1445,40 @@ void PDFDoc::markObject (Object* obj, XR
case objArray:
array = obj->getArray();
for (int i=0; i<array->getLength(); i++) {
- markObject(array->getNF(i, &obj1), xRef, countRef, numOffset);
+ const bool success = markObject(array->getNF(i, &obj1), xRef, countRef, numOffset);
+ if (unlikely(!success)) {
+ return false;
+ }
obj1.free();
}
break;
case objDict:
- markDictionnary (obj->getDict(), xRef, countRef, numOffset);
+ {
+ int success = markDictionnary (obj->getDict(), xRef, countRef, numOffset);
+ if (unlikely(!success)) {
+ return false;
+ }
+ }
break;
case objStream:
{
Stream *stream = obj->getStream();
- markDictionnary (stream->getDict(), xRef, countRef, numOffset);
+ const bool success = markDictionnary (stream->getDict(), xRef, countRef, numOffset);
+ 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 true; // 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;
}
@@ -1469,13 +1495,18 @@ void PDFDoc::markObject (Object* obj, XR
}
Object obj1;
getXRef()->fetch(obj->getRef().num, obj->getRef().gen, &obj1);
- markObject(&obj1, xRef, countRef, numOffset);
+ const bool success = markObject(&obj1, xRef, countRef, numOffset);
+ if (unlikely(!success)) {
+ return false;
+ }
obj1.free();
}
break;
default:
break;
}
+
+ return true;
}
void PDFDoc::replacePageDict(int pageNo, int rotate,
@@ -1559,7 +1590,7 @@ void PDFDoc::replacePageDict(int pageNo,
page.free();
}
-void PDFDoc::markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint numOffset)
+bool PDFDoc::markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint numOffset)
{
pageDict->remove("Names");
pageDict->remove("OpenAction");
@@ -1572,10 +1603,14 @@ void PDFDoc::markPageObjects(Dict *pageD
if (strcmp(key, "Parent") != 0 &&
strcmp(key, "Pages") != 0 &&
strcmp(key, "Root") != 0) {
- markObject(&value, xRef, countRef, numOffset);
+ const bool success = markObject(&value, xRef, countRef, numOffset);
+ if (unlikely(!success)) {
+ return false;
+ }
}
value.free();
}
+ return true;
}
Guint PDFDoc::writePageObjects(OutStream *outStr, XRef *xRef, Guint numOffset, GBool combine)
Index: poppler-0.24.4/poppler/PDFDoc.h
===================================================================
--- poppler-0.24.4.orig/poppler/PDFDoc.h
+++ poppler-0.24.4/poppler/PDFDoc.h
@@ -246,7 +246,7 @@ public:
// rewrite pageDict with MediaBox, CropBox and new page CTM
void replacePageDict(int pageNo, int rotate, PDFRectangle *mediaBox, PDFRectangle *cropBox, Object *pageCTM);
- void markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint numOffset);
+ bool markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint numOffset);
// write all objects used by pageDict to outStr
Guint writePageObjects(OutStream *outStr, XRef *xRef, Guint numOffset, GBool combine = gFalse);
static void writeObject (Object *obj, OutStream* outStr, XRef *xref, Guint numOffset, Guchar *fileKey,
@@ -263,8 +263,8 @@ public:
private:
// insert referenced objects in XRef
- void markDictionnary (Dict* dict, XRef *xRef, XRef *countRef, Guint numOffset);
- void markObject (Object *obj, XRef *xRef, XRef *countRef, Guint numOffset);
+ bool markDictionnary (Dict* dict, XRef *xRef, XRef *countRef, Guint numOffset);
+ bool markObject (Object *obj, XRef *xRef, XRef *countRef, Guint numOffset);
static void writeDictionnary (Dict* dict, OutStream* outStr, XRef *xRef, Guint numOffset, Guchar *fileKey,
CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen);
Index: poppler-0.24.4/poppler/XRef.cc
===================================================================
--- poppler-0.24.4.orig/poppler/XRef.cc
+++ poppler-0.24.4/poppler/XRef.cc
@@ -1325,11 +1325,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) {
@@ -1352,6 +1357,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.24.4/poppler/XRef.h
===================================================================
--- poppler-0.24.4.orig/poppler/XRef.h
+++ poppler-0.24.4/poppler/XRef.h
@@ -180,7 +180,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);