summaryrefslogtreecommitdiff
path: root/Build/source/libs/poppler/poppler-src/poppler/XRef.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/poppler/poppler-src/poppler/XRef.cc')
-rw-r--r--Build/source/libs/poppler/poppler-src/poppler/XRef.cc484
1 files changed, 208 insertions, 276 deletions
diff --git a/Build/source/libs/poppler/poppler-src/poppler/XRef.cc b/Build/source/libs/poppler/poppler-src/poppler/XRef.cc
index e5ecd632a51..f04a31fc1ed 100644
--- a/Build/source/libs/poppler/poppler-src/poppler/XRef.cc
+++ b/Build/source/libs/poppler/poppler-src/poppler/XRef.cc
@@ -15,14 +15,14 @@
//
// Copyright (C) 2005 Dan Sheridan <dan.sheridan@postman.org.uk>
// Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
-// Copyright (C) 2006, 2008, 2010, 2012-2014, 2016 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2006, 2008, 2010, 2012-2014, 2016, 2017 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2007-2008 Julien Rebetez <julienr@svn.gnome.org>
// Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
// Copyright (C) 2009, 2010 Ilya Gorenbein <igorenbein@finjan.com>
// Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
// Copyright (C) 2012, 2013, 2016 Thomas Freitag <Thomas.Freitag@kabelmail.de>
// Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso@hotmail.it>
-// Copyright (C) 2013, 2014 Adrian Johnson <ajohnson@redneon.com>
+// Copyright (C) 2013, 2014, 2017 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2013 Pino Toscano <pino@kde.org>
// Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com>
//
@@ -32,6 +32,7 @@
//========================================================================
#include <config.h>
+#include "poppler-config.h"
#ifdef USE_GCC_PRAGMAS
#pragma implementation
@@ -71,7 +72,7 @@
#define permHighResPrint (1<<11) // bit 12
#define defPermFlags 0xfffc
-#if MULTITHREADED
+#ifdef MULTITHREADED
# define xrefLocker() MutexLocker locker(&mutex)
# define xrefCondLocker(X) MutexLocker locker(&mutex, (X))
#else
@@ -99,7 +100,7 @@ public:
// Get the <objIdx>th object from this stream, which should be
// object number <objNum>, generation 0.
- Object *getObject(int objIdx, int objNum, Object *obj);
+ Object getObject(int objIdx, int objNum);
private:
@@ -117,7 +118,7 @@ class ObjectStreamKey : public PopplerCacheKey
{
}
- bool operator==(const PopplerCacheKey &key) const
+ bool operator==(const PopplerCacheKey &key) const override
{
const ObjectStreamKey *k = static_cast<const ObjectStreamKey*>(&key);
return objStrNum == k->objStrNum;
@@ -145,7 +146,7 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA, int recursion) {
Stream *str;
Parser *parser;
Goffset *offsets;
- Object objStr, obj1, obj2;
+ Object objStr, obj1;
Goffset first;
int i;
@@ -155,32 +156,30 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA, int recursion) {
objNums = NULL;
ok = gFalse;
- if (!xref->fetch(objStrNum, 0, &objStr, recursion)->isStream()) {
- goto err1;
+ objStr = xref->fetch(objStrNum, 0, recursion);
+ if (!objStr.isStream()) {
+ return;
}
- if (!objStr.streamGetDict()->lookup("N", &obj1, recursion)->isInt()) {
- obj1.free();
- goto err1;
+ obj1 = objStr.streamGetDict()->lookup("N", recursion);
+ if (!obj1.isInt()) {
+ return;
}
nObjects = obj1.getInt();
- obj1.free();
if (nObjects <= 0) {
- goto err1;
+ return;
}
- objStr.streamGetDict()->lookup("First", &obj1, recursion);
+ obj1 = objStr.streamGetDict()->lookup("First", recursion);
if (!obj1.isInt() && !obj1.isInt64()) {
- obj1.free();
- goto err1;
+ return;
}
if (obj1.isInt())
first = obj1.getInt();
else
first = obj1.getInt64();
- obj1.free();
if (first < 0) {
- goto err1;
+ return;
}
// this is an arbitrary limit to avoid integer overflow problems
@@ -188,7 +187,7 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA, int recursion) {
// object streams to 100-200 objects)
if (nObjects > 1000000) {
error(errSyntaxError, -1, "Too many objects in an object stream");
- goto err1;
+ return;
}
objs = new Object[nObjects];
objNums = (int *)gmallocn(nObjects, sizeof(int));
@@ -196,31 +195,26 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA, int recursion) {
// parse the header: object numbers and offsets
objStr.streamReset();
- obj1.initNull();
- str = new EmbedStream(objStr.getStream(), &obj1, gTrue, first);
+ str = new EmbedStream(objStr.getStream(), Object(objNull), gTrue, first);
parser = new Parser(xref, new Lexer(xref, str), gFalse);
for (i = 0; i < nObjects; ++i) {
- parser->getObj(&obj1);
- parser->getObj(&obj2);
+ obj1 = parser->getObj();
+ Object obj2 = parser->getObj();
if (!obj1.isInt() || !(obj2.isInt() || obj2.isInt64())) {
- obj1.free();
- obj2.free();
delete parser;
gfree(offsets);
- goto err1;
+ return;
}
objNums[i] = obj1.getInt();
if (obj2.isInt())
offsets[i] = obj2.getInt();
else
offsets[i] = obj2.getInt64();
- obj1.free();
- obj2.free();
if (objNums[i] < 0 || offsets[i] < 0 ||
(i > 0 && offsets[i] < offsets[i-1])) {
delete parser;
gfree(offsets);
- goto err1;
+ return;
}
}
while (str->getChar() != EOF) ;
@@ -235,43 +229,32 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA, int recursion) {
// parse the objects
for (i = 0; i < nObjects; ++i) {
- obj1.initNull();
if (i == nObjects - 1) {
- str = new EmbedStream(objStr.getStream(), &obj1, gFalse, 0);
+ str = new EmbedStream(objStr.getStream(), Object(objNull), gFalse, 0);
} else {
- str = new EmbedStream(objStr.getStream(), &obj1, gTrue,
+ str = new EmbedStream(objStr.getStream(), Object(objNull), gTrue,
offsets[i+1] - offsets[i]);
}
parser = new Parser(xref, new Lexer(xref, str), gFalse);
- parser->getObj(&objs[i]);
+ objs[i] = parser->getObj();
while (str->getChar() != EOF) ;
delete parser;
}
gfree(offsets);
ok = gTrue;
-
- err1:
- objStr.free();
}
ObjectStream::~ObjectStream() {
- int i;
-
- if (objs) {
- for (i = 0; i < nObjects; ++i) {
- objs[i].free();
- }
- delete[] objs;
- }
+ delete[] objs;
gfree(objNums);
}
-Object *ObjectStream::getObject(int objIdx, int objNum, Object *obj) {
+Object ObjectStream::getObject(int objIdx, int objNum) {
if (objIdx < 0 || objIdx >= nObjects || objNum != objNums[objIdx]) {
- return obj->initNull();
+ return Object(objNull);
}
- return objs[objIdx].copy(obj);
+ return objs[objIdx].copy();
}
//------------------------------------------------------------------------
@@ -279,7 +262,7 @@ Object *ObjectStream::getObject(int objIdx, int objNum, Object *obj) {
//------------------------------------------------------------------------
void XRef::init() {
-#if MULTITHREADED
+#ifdef MULTITHREADED
gInitMutex(&mutex);
#endif
ok = gTrue;
@@ -311,7 +294,7 @@ XRef::XRef(Object *trailerDictA) {
init();
if (trailerDictA->isDict())
- trailerDict.initDict(trailerDictA->getDict());
+ trailerDict = trailerDictA->copy();
}
XRef::XRef(BaseStream *strA, Goffset pos, Goffset mainXRefEntriesOffsetA, GBool *wasReconstructed, GBool reconstruct) {
@@ -356,30 +339,26 @@ XRef::XRef(BaseStream *strA, Goffset pos, Goffset mainXRefEntriesOffsetA, GBool
}
// set size to (at least) the size specified in trailer dict
- trailerDict.dictLookupNF("Size", &obj);
+ obj = trailerDict.dictLookupNF("Size");
if (!obj.isInt()) {
error(errSyntaxWarning, -1, "No valid XRef size in trailer");
} else {
if (obj.getInt() > size) {
if (resize(obj.getInt()) != obj.getInt()) {
if (!(ok = constructXRef(wasReconstructed))) {
- obj.free();
errCode = errDamaged;
return;
}
}
}
}
- obj.free();
// get the root dictionary (catalog) object
- trailerDict.dictLookupNF("Root", &obj);
+ obj = trailerDict.dictLookupNF("Root");
if (obj.isRef()) {
rootNum = obj.getRefNum();
rootGen = obj.getRefGen();
- obj.free();
} else {
- obj.free();
if (!(ok = constructXRef(wasReconstructed))) {
errCode = errDamaged;
return;
@@ -397,7 +376,6 @@ XRef::~XRef() {
}
gfree(entries);
- trailerDict.free();
if (streamEnds) {
gfree(streamEnds);
}
@@ -407,7 +385,7 @@ XRef::~XRef() {
if (strOwner) {
delete str;
}
-#if MULTITHREADED
+#ifdef MULTITHREADED
gDestroyMutex(&mutex);
#endif
}
@@ -426,7 +404,7 @@ XRef *XRef::copy() {
xref->prevXRefOffset = prevXRefOffset;
xref->mainXRefEntriesOffset = mainXRefEntriesOffset;
xref->xRefStream = xRefStream;
- trailerDict.copy(&xref->trailerDict);
+ xref->trailerDict = trailerDict.copy();
xref->encAlgorithm = encAlgorithm;
xref->encRevision = encRevision;
xref->encVersion = encVersion;
@@ -446,7 +424,7 @@ XRef *XRef::copy() {
for (int i = 0; i < size; ++i) {
xref->entries[i].offset = entries[i].offset;
xref->entries[i].type = entries[i].type;
- xref->entries[i].obj.initNull ();
+ xref->entries[i].obj.initNullAfterMalloc();
xref->entries[i].flags = entries[i].flags;
xref->entries[i].gen = entries[i].gen;
}
@@ -495,7 +473,7 @@ int XRef::resize(int newSize)
for (int i = size; i < newSize; ++i) {
entries[i].offset = -1;
entries[i].type = xrefEntryNone;
- entries[i].obj.initNull ();
+ entries[i].obj.initNullAfterMalloc ();
entries[i].flags = 0;
entries[i].gen = 0;
}
@@ -529,31 +507,26 @@ GBool XRef::readXRef(Goffset *pos, std::vector<Goffset> *followedXRefStm, std::v
GBool more;
// start up a parser, parse one token
- obj.initNull();
parser = new Parser(NULL,
new Lexer(NULL,
- str->makeSubStream(start + *pos, gFalse, 0, &obj)),
+ str->makeSubStream(start + *pos, gFalse, 0, Object(objNull))),
gTrue);
- parser->getObj(&obj, gTrue);
+ obj = parser->getObj(gTrue);
// parse an old-style xref table
if (obj.isCmd("xref")) {
- obj.free();
more = readXRefTable(parser, pos, followedXRefStm, xrefStreamObjsNum);
// parse an xref stream
} else if (obj.isInt()) {
const int objNum = obj.getInt();
- obj.free();
- if (!parser->getObj(&obj, gTrue)->isInt()) {
+ if (obj = parser->getObj(gTrue), !obj.isInt()) {
goto err1;
}
- obj.free();
- if (!parser->getObj(&obj, gTrue)->isCmd("obj")) {
+ if (obj = parser->getObj(gTrue), !obj.isCmd("obj")) {
goto err1;
}
- obj.free();
- if (!parser->getObj(&obj)->isStream()) {
+ if (obj = parser->getObj(), !obj.isStream()) {
goto err1;
}
if (trailerDict.isNone()) {
@@ -563,7 +536,6 @@ GBool XRef::readXRef(Goffset *pos, std::vector<Goffset> *followedXRefStm, std::v
xrefStreamObjsNum->push_back(objNum);
}
more = readXRefStream(obj.getStream(), pos);
- obj.free();
} else {
goto err1;
@@ -573,7 +545,6 @@ GBool XRef::readXRef(Goffset *pos, std::vector<Goffset> *followedXRefStm, std::v
return more;
err1:
- obj.free();
delete parser;
ok = gFalse;
return gFalse;
@@ -587,21 +558,19 @@ GBool XRef::readXRefTable(Parser *parser, Goffset *pos, std::vector<Goffset> *fo
int first, n, i;
while (1) {
- parser->getObj(&obj, gTrue);
+ obj = parser->getObj(gTrue);
if (obj.isCmd("trailer")) {
- obj.free();
break;
}
if (!obj.isInt()) {
- goto err1;
+ goto err0;
}
first = obj.getInt();
- obj.free();
- if (!parser->getObj(&obj, gTrue)->isInt()) {
- goto err1;
+ obj = parser->getObj(gTrue);
+ if (!obj.isInt()) {
+ goto err0;
}
n = obj.getInt();
- obj.free();
if (first < 0 || n < 0 || first + n < 0) {
goto err0;
}
@@ -612,33 +581,35 @@ GBool XRef::readXRefTable(Parser *parser, Goffset *pos, std::vector<Goffset> *fo
}
}
for (i = first; i < first + n; ++i) {
- parser->getObj(&obj, gTrue);
+ obj = parser->getObj(gTrue);
if (obj.isInt()) {
entry.offset = obj.getInt();
} else if (obj.isInt64()) {
entry.offset = obj.getInt64();
} else {
- goto err1;
+ goto err0;
}
- obj.free();
- if (!parser->getObj(&obj, gTrue)->isInt()) {
- goto err1;
+ obj = parser->getObj(gTrue);
+ if (!obj.isInt()) {
+ goto err0;
}
entry.gen = obj.getInt();
- entry.obj.initNull ();
entry.flags = 0;
- obj.free();
- parser->getObj(&obj, gTrue);
+ obj = parser->getObj(gTrue);
if (obj.isCmd("n")) {
entry.type = xrefEntryUncompressed;
} else if (obj.isCmd("f")) {
entry.type = xrefEntryFree;
} else {
- goto err1;
+ goto err0;
}
- obj.free();
if (entries[i].offset == -1) {
- entries[i] = entry;
+ entries[i].offset = entry.offset;
+ entries[i].gen = entry.gen;
+ entries[i].type = entry.type;
+ entries[i].flags = entry.flags;
+ entries[i].obj.setToNull();
+
// PDF files of patents from the IBM Intellectual Property
// Network have a bug: the xref table claims to start at 1
// instead of 0.
@@ -646,7 +617,12 @@ GBool XRef::readXRefTable(Parser *parser, Goffset *pos, std::vector<Goffset> *fo
entries[1].offset == 0 && entries[1].gen == 65535 &&
entries[1].type == xrefEntryFree) {
i = first = 0;
- entries[0] = entries[1];
+ entries[0].offset = 0;
+ entries[0].gen = 65535;
+ entries[0].type = xrefEntryFree;
+ entries[0].flags = entries[1].flags;
+ entries[0].obj = std::move(entries[1].obj);
+
entries[1].offset = -1;
}
}
@@ -654,12 +630,13 @@ GBool XRef::readXRefTable(Parser *parser, Goffset *pos, std::vector<Goffset> *fo
}
// read the trailer dictionary
- if (!parser->getObj(&obj)->isDict()) {
- goto err1;
+ obj = parser->getObj();
+ if (!obj.isDict()) {
+ goto err0;
}
// get the 'Prev' pointer
- obj.getDict()->lookupNF("Prev", &obj2);
+ obj2 = obj.getDict()->lookupNF("Prev");
if (obj2.isInt() || obj2.isInt64()) {
if (obj2.isInt())
pos2 = obj2.getInt();
@@ -686,15 +663,14 @@ GBool XRef::readXRefTable(Parser *parser, Goffset *pos, std::vector<Goffset> *fo
} else {
more = gFalse;
}
- obj2.free();
// save the first trailer dictionary
if (trailerDict.isNone()) {
- obj.copy(&trailerDict);
+ trailerDict = obj.copy();
}
// check for an 'XRefStm' key
- obj.getDict()->lookup("XRefStm", &obj2);
+ obj2 = obj.getDict()->lookup("XRefStm");
if (obj2.isInt() || obj2.isInt64()) {
if (obj2.isInt())
pos2 = obj2.getInt();
@@ -710,97 +686,84 @@ GBool XRef::readXRefTable(Parser *parser, Goffset *pos, std::vector<Goffset> *fo
readXRef(&pos2, followedXRefStm, xrefStreamObjsNum);
}
if (!ok) {
- obj2.free();
- goto err1;
+ goto err0;
}
}
- obj2.free();
- obj.free();
return more;
- err1:
- obj.free();
err0:
ok = gFalse;
return gFalse;
}
GBool XRef::readXRefStream(Stream *xrefStr, Goffset *pos) {
- Dict *dict;
int w[3];
GBool more;
- Object obj, obj2, idx;
- int newSize, first, n, i;
+ Object obj;
- dict = xrefStr->getDict();
+ ok = gFalse;
- if (!dict->lookupNF("Size", &obj)->isInt()) {
- goto err1;
+ Dict *dict = xrefStr->getDict();
+ obj = dict->lookupNF("Size");
+ if (!obj.isInt()) {
+ return gFalse;
}
- newSize = obj.getInt();
- obj.free();
+ int newSize = obj.getInt();
if (newSize < 0) {
- goto err1;
+ return gFalse;
}
if (newSize > size) {
if (resize(newSize) != newSize) {
error(errSyntaxError, -1, "Invalid 'size' parameter");
- goto err0;
+ return gFalse;
}
}
- if (!dict->lookupNF("W", &obj)->isArray() ||
- obj.arrayGetLength() < 3) {
- goto err1;
+ obj = dict->lookupNF("W");
+ if (!obj.isArray() || obj.arrayGetLength() < 3) {
+ return gFalse;
}
- for (i = 0; i < 3; ++i) {
- if (!obj.arrayGet(i, &obj2)->isInt()) {
- obj2.free();
- goto err1;
+ for (int i = 0; i < 3; ++i) {
+ Object obj2 = obj.arrayGet(i);
+ if (!obj2.isInt()) {
+ return gFalse;
}
w[i] = obj2.getInt();
- obj2.free();
if (w[i] < 0) {
- goto err1;
+ return gFalse;
}
}
- obj.free();
- if (w[0] > (int)sizeof(int) || w[1] > (int)sizeof(long long) || w[2] > (int)sizeof(int)) {
- goto err1;
+ if (w[0] > (int)sizeof(int) || w[1] > (int)sizeof(long long) || w[2] > (int)sizeof(long long)) {
+ return gFalse;
}
xrefStr->reset();
- dict->lookupNF("Index", &idx);
+ Object idx = dict->lookupNF("Index");
if (idx.isArray()) {
- for (i = 0; i+1 < idx.arrayGetLength(); i += 2) {
- if (!idx.arrayGet(i, &obj)->isInt()) {
- idx.free();
- goto err1;
+ for (int i = 0; i+1 < idx.arrayGetLength(); i += 2) {
+ obj = idx.arrayGet(i);
+ if (!obj.isInt()) {
+ return gFalse;
}
- first = obj.getInt();
- obj.free();
- if (!idx.arrayGet(i+1, &obj)->isInt()) {
- idx.free();
- goto err1;
+ int first = obj.getInt();
+ obj = idx.arrayGet(i+1);
+ if (!obj.isInt()) {
+ return gFalse;
}
- n = obj.getInt();
- obj.free();
+ int n = obj.getInt();
if (first < 0 || n < 0 ||
!readXRefStreamSection(xrefStr, w, first, n)) {
- idx.free();
- goto err0;
+ return gFalse;
}
}
} else {
if (!readXRefStreamSection(xrefStr, w, 0, newSize)) {
- idx.free();
- goto err0;
+ return gFalse;
}
}
- idx.free();
- dict->lookupNF("Prev", &obj);
+ obj = dict->lookupNF("Prev");
if (obj.isInt()) {
*pos = obj.getInt();
more = gTrue;
@@ -810,23 +773,17 @@ GBool XRef::readXRefStream(Stream *xrefStr, Goffset *pos) {
} else {
more = gFalse;
}
- obj.free();
if (trailerDict.isNone()) {
- trailerDict.initDict(dict);
+ trailerDict = xrefStr->getDictObject()->copy();
}
+ ok = gTrue;
return more;
-
- err1:
- obj.free();
- err0:
- ok = gFalse;
- return gFalse;
}
GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) {
- unsigned long long offset;
- int type, gen, c, i, j;
+ unsigned long long offset, gen;
+ int type, c, i, j;
if (first + n < 0) {
return gFalse;
@@ -868,6 +825,10 @@ GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) {
}
gen = (gen << 8) + c;
}
+ if (gen > INT_MAX) {
+ error(errSyntaxError, -1, "Gen inside xref table too large (bigger than INT_MAX)");
+ return gFalse;
+ }
if (entries[i].offset == -1) {
switch (type) {
case 0:
@@ -897,7 +858,7 @@ GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) {
// Attempt to construct an xref table for a damaged file.
GBool XRef::constructXRef(GBool *wasReconstructed, GBool needCatalogDict) {
Parser *parser;
- Object newTrailerDict, obj;
+ Object obj;
char buf[256];
Goffset pos;
int num, gen;
@@ -909,6 +870,7 @@ GBool XRef::constructXRef(GBool *wasReconstructed, GBool needCatalogDict) {
bool oneCycle = true;
int offset = 0;
+ resize(0); // free entries properly
gfree(entries);
capacity = 0;
size = 0;
@@ -947,26 +909,20 @@ GBool XRef::constructXRef(GBool *wasReconstructed, GBool needCatalogDict) {
// got trailer dictionary
if (!strncmp(p, "trailer", 7)) {
- obj.initNull();
parser = new Parser(NULL,
new Lexer(NULL,
- str->makeSubStream(pos + 7, gFalse, 0, &obj)),
+ str->makeSubStream(pos + 7, gFalse, 0, Object(objNull))),
gFalse);
- parser->getObj(&newTrailerDict);
+ Object newTrailerDict = parser->getObj();
if (newTrailerDict.isDict()) {
- newTrailerDict.dictLookupNF("Root", &obj);
+ obj = newTrailerDict.dictLookupNF("Root");
if (obj.isRef() && (!gotRoot || !needCatalogDict) && rootNum != obj.getRefNum()) {
rootNum = obj.getRefNum();
rootGen = obj.getRefGen();
- if (!trailerDict.isNone()) {
- trailerDict.free();
- }
- newTrailerDict.copy(&trailerDict);
+ trailerDict = newTrailerDict.copy();
gotRoot = gTrue;
}
- obj.free();
}
- newTrailerDict.free();
delete parser;
// look for object
@@ -1023,17 +979,25 @@ GBool XRef::constructXRef(GBool *wasReconstructed, GBool needCatalogDict) {
}
}
- } else if (!strncmp(p, "endstream", 9)) {
- if (streamEndsLen == streamEndsSize) {
- streamEndsSize += 64;
- if (streamEndsSize >= INT_MAX / (int)sizeof(int)) {
- error(errSyntaxError, -1, "Invalid 'endstream' parameter.");
- return gFalse;
- }
- streamEnds = (Goffset *)greallocn(streamEnds,
- streamEndsSize, sizeof(Goffset));
- }
- streamEnds[streamEndsLen++] = pos;
+ } else {
+ char *endstream = strstr( p, "endstream" );
+ if (endstream) {
+ int endstreamPos = endstream - p;
+ if ((endstreamPos == 0 || Lexer::isSpace(p[endstreamPos-1] & 0xff)) // endstream is either at beginning or preceeded by space
+ && (endstreamPos + 9 >= 256 || Lexer::isSpace(p[endstreamPos+9] & 0xff))) // endstream is either at end or followed by space
+ {
+ if (streamEndsLen == streamEndsSize) {
+ streamEndsSize += 64;
+ if (streamEndsSize >= INT_MAX / (int)sizeof(int)) {
+ error(errSyntaxError, -1, "Invalid 'endstream' parameter.");
+ return gFalse;
+ }
+ streamEnds = (Goffset *)greallocn(streamEnds,
+ streamEndsSize, sizeof(Goffset));
+ }
+ streamEnds[streamEndsLen++] = pos + endstreamPos;
+ }
+ }
}
if( token ) {
p = token + 6;// strlen( "endobj" ) = 6
@@ -1135,17 +1099,19 @@ GBool XRef::okToAssemble(GBool ignoreOwnerPW) {
return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permAssemble);
}
-Object *XRef::getCatalog(Object *catalog) {
- Object *obj = fetch(rootNum, rootGen, catalog);
- if (obj->isDict()) {
- return obj;
+Object XRef::getCatalog() {
+ Object catalog = fetch(rootNum, rootGen);
+ if (catalog.isDict()) {
+ return catalog;
}
GBool wasReconstructed = false;
- GBool ok = constructXRef(&wasReconstructed, gTrue);
- return (ok) ? fetch(rootNum, rootGen, catalog) : obj;
+ if (constructXRef(&wasReconstructed, gTrue)) {
+ catalog = fetch(rootNum, rootGen);
+ }
+ return catalog;
}
-Object *XRef::fetch(int num, int gen, Object *obj, int recursion) {
+Object XRef::fetch(int num, int gen, int recursion) {
XRefEntry *e;
Parser *parser;
Object obj1, obj2, obj3;
@@ -1158,24 +1124,23 @@ Object *XRef::fetch(int num, int gen, Object *obj, int recursion) {
e = getEntry(num);
if(!e->obj.isNull ()) { //check for updated object
- obj = e->obj.copy(obj);
- return obj;
+ return e->obj.copy();
}
switch (e->type) {
case xrefEntryUncompressed:
+ {
if (e->gen != gen) {
goto err;
}
- obj1.initNull();
parser = new Parser(this,
new Lexer(this,
- str->makeSubStream(start + e->offset, gFalse, 0, &obj1)),
+ str->makeSubStream(start + e->offset, gFalse, 0, Object(objNull))),
gTrue);
- parser->getObj(&obj1, recursion);
- parser->getObj(&obj2, recursion);
- parser->getObj(&obj3, recursion);
+ obj1 = parser->getObj(recursion);
+ obj2 = parser->getObj(recursion);
+ obj3 = parser->getObj(recursion);
if (!obj1.isInt() || obj1.getInt() != num ||
!obj2.isInt() || obj2.getInt() != gen ||
!obj3.isCmd("obj")) {
@@ -1194,28 +1159,19 @@ Object *XRef::fetch(int num, int gen, Object *obj, int recursion) {
if (longNumber <= INT_MAX && longNumber >= INT_MIN && *end_ptr == '\0') {
int number = longNumber;
error(errSyntaxWarning, -1, "Cmd was not obj but {0:s}, assuming the creator meant obj {1:d}", cmd, number);
- obj->initInt(number);
- obj1.free();
- obj2.free();
- obj3.free();
delete parser;
- break;
+ return Object(number);
}
}
}
- obj1.free();
- obj2.free();
- obj3.free();
delete parser;
goto err;
}
- parser->getObj(obj, gFalse, (encrypted && !e->getFlag(XRefEntry::Unencrypted)) ? fileKey : NULL,
+ Object obj = parser->getObj(gFalse, (encrypted && !e->getFlag(XRefEntry::Unencrypted)) ? fileKey : NULL,
encAlgorithm, keyLength, num, gen, recursion);
- obj1.free();
- obj2.free();
- obj3.free();
delete parser;
- break;
+ return obj;
+ }
case xrefEntryCompressed:
{
@@ -1252,75 +1208,63 @@ Object *XRef::fetch(int num, int gen, Object *obj, int recursion) {
objStrs->put(newkey, newitem);
}
}
- objStr->getObject(e->gen, num, obj);
+ return objStr->getObject(e->gen, num);
}
- break;
default:
goto err;
}
- return obj;
-
err:
if (!xRefStream && !xrefReconstructed) {
error(errInternal, -1, "xref num {0:d} not found but needed, try to reconstruct\n", num);
rootNum = -1;
constructXRef(&xrefReconstructed);
- return fetch(num, gen, obj, ++recursion);
+ return fetch(num, gen, ++recursion);
}
- return obj->initNull();
+ return Object(objNull);
}
void XRef::lock() {
-#if MULTITHREADED
+#ifdef MULTITHREADED
gLockMutex(&mutex);
#endif
}
void XRef::unlock() {
-#if MULTITHREADED
+#ifdef MULTITHREADED
gUnlockMutex(&mutex);
#endif
}
-Object *XRef::getDocInfo(Object *obj) {
- return trailerDict.dictLookup("Info", obj);
+Object XRef::getDocInfo() {
+ return trailerDict.dictLookup("Info");
}
// Added for the pdftex project.
-Object *XRef::getDocInfoNF(Object *obj) {
- return trailerDict.dictLookupNF("Info", obj);
+Object XRef::getDocInfoNF() {
+ return trailerDict.dictLookupNF("Info");
}
-Object *XRef::createDocInfoIfNoneExists(Object *obj) {
- getDocInfo(obj);
+Object XRef::createDocInfoIfNoneExists() {
+ Object obj = getDocInfo();
- if (obj->isDict()) {
+ if (obj.isDict()) {
return obj;
- } else if (!obj->isNull()) {
+ } else if (!obj.isNull()) {
// DocInfo exists, but isn't a dictionary (doesn't comply with the PDF reference)
- obj->free();
removeDocInfo();
}
- obj->initDict(this);
-
- Ref ref = addIndirectObject(obj);
-
- Object objRef;
- objRef.initRef(ref.num, ref.gen);
-
- trailerDict.dictSet("Info", &objRef);
-
- objRef.free();
+ obj = Object(new Dict(this));
+ const Ref ref = addIndirectObject(&obj);
+ trailerDict.dictSet("Info", Object(ref.num, ref.gen));
return obj;
}
void XRef::removeDocInfo() {
- Object infoObjRef;
- getDocInfoNF(&infoObjRef);
+ Object infoObjRef = getDocInfoNF();
if (infoObjRef.isNull()) {
return;
}
@@ -1328,7 +1272,6 @@ void XRef::removeDocInfo() {
trailerDict.dictRemove("Info");
removeIndirectObject(infoObjRef.getRef());
- infoObjRef.free();
}
GBool XRef::getStreamEnd(Goffset streamStart, Goffset *streamEnd) {
@@ -1385,7 +1328,7 @@ void XRef::add(int num, int gen, Goffset offs, GBool used) {
for (int i = size; i < num + 1; ++i) {
entries[i].offset = -1;
entries[i].type = xrefEntryFree;
- entries[i].obj.initNull ();
+ entries[i].obj.initNullAfterMalloc();
entries[i].flags = 0;
entries[i].gen = 0;
}
@@ -1393,7 +1336,7 @@ void XRef::add(int num, int gen, Goffset offs, GBool used) {
}
XRefEntry *e = getEntry(num);
e->gen = gen;
- e->obj.initNull ();
+ e->obj.setToNull();
e->flags = 0;
if (used) {
e->type = xrefEntryUncompressed;
@@ -1411,8 +1354,7 @@ void XRef::setModifiedObject (Object* o, Ref r) {
return;
}
XRefEntry *e = getEntry(r.num);
- e->obj.free();
- o->copy(&(e->obj));
+ e->obj = o->copy();
e->setFlag(XRefEntry::Updated, gTrue);
setModified();
}
@@ -1438,7 +1380,7 @@ Ref XRef::addIndirectObject (Object* o) {
//incremented when the object was deleted
}
e->type = xrefEntryUncompressed;
- o->copy(&e->obj);
+ e->obj = o->copy();
e->setFlag(XRefEntry::Updated, gTrue);
setModified();
@@ -1527,16 +1469,15 @@ void XRef::writeTableToFile(OutStream* outStr, GBool writeAllEntries) {
writeXRef(&writer, writeAllEntries);
}
-XRef::XRefStreamWriter::XRefStreamWriter(Object *indexA, GooString *stmBufA, int offsetSizeA) {
+XRef::XRefStreamWriter::XRefStreamWriter(Array *indexA, GooString *stmBufA, int offsetSizeA) {
index = indexA;
stmBuf = stmBufA;
offsetSize = offsetSizeA;
}
void XRef::XRefStreamWriter::startSection(int first, int count) {
- Object obj;
- index->arrayAdd( obj.initInt(first) );
- index->arrayAdd( obj.initInt(count) );
+ index->add( Object(first) );
+ index->add( Object(count) );
}
void XRef::XRefStreamWriter::writeEntry(Goffset offset, int gen, XRefEntryType type) {
@@ -1565,8 +1506,7 @@ void XRef::XRefPreScanWriter::writeEntry(Goffset offset, int gen, XRefEntryType
}
void XRef::writeStreamToBuffer(GooString *stmBuf, Dict *xrefDict, XRef *xref) {
- Object index;
- index.initArray(xref);
+ Array *index = new Array(xref);
stmBuf->clear();
// First pass: determine whether all offsets fit in 4 bytes or not
@@ -1575,48 +1515,44 @@ void XRef::writeStreamToBuffer(GooString *stmBuf, Dict *xrefDict, XRef *xref) {
const int offsetSize = prescan.hasOffsetsBeyond4GB ? sizeof(Goffset) : 4;
// Second pass: actually write the xref stream
- XRefStreamWriter writer(&index, stmBuf, offsetSize);
+ XRefStreamWriter writer(index, stmBuf, offsetSize);
writeXRef(&writer, gFalse);
- Object obj1, obj2;
- xrefDict->set("Type", obj1.initName("XRef"));
- xrefDict->set("Index", &index);
- obj2.initArray(xref);
- obj2.arrayAdd( obj1.initInt(1) );
- obj2.arrayAdd( obj1.initInt(offsetSize) );
- obj2.arrayAdd( obj1.initInt(2) );
- xrefDict->set("W", &obj2);
+ xrefDict->set("Type", Object(objName, "XRef"));
+ xrefDict->set("Index", Object(index));
+ Array *wArray = new Array(xref);
+ wArray->add( Object(1) );
+ wArray->add( Object(offsetSize) );
+ wArray->add( Object(2) );
+ xrefDict->set("W", Object(wArray));
}
GBool XRef::parseEntry(Goffset offset, XRefEntry *entry)
{
GBool r;
- Object obj;
- obj.initNull();
- Parser parser = Parser(NULL, new Lexer(NULL,
- str->makeSubStream(offset, gFalse, 20, &obj)), gTrue);
+ if (unlikely(entry == nullptr))
+ return gFalse;
+
+ Parser parser(NULL, new Lexer(NULL,
+ str->makeSubStream(offset, gFalse, 20, Object(objNull))), gTrue);
Object obj1, obj2, obj3;
- if (((parser.getObj(&obj1)->isInt()) ||
- parser.getObj(&obj1)->isInt64()) &&
- (parser.getObj(&obj2)->isInt()) &&
- (parser.getObj(&obj3)->isCmd("n") || obj3.isCmd("f"))) {
+ if (((obj1 = parser.getObj(), obj1.isInt()) || obj1.isInt64()) &&
+ (obj2 = parser.getObj(), obj2.isInt()) &&
+ (obj3 = parser.getObj(), obj3.isCmd("n") || obj3.isCmd("f"))) {
if (obj1.isInt64())
entry->offset = obj1.getInt64();
else
entry->offset = obj1.getInt();
entry->gen = obj2.getInt();
entry->type = obj3.isCmd("n") ? xrefEntryUncompressed : xrefEntryFree;
- entry->obj.initNull ();
+ entry->obj.setToNull();
entry->flags = 0;
r = gTrue;
} else {
r = gFalse;
}
- obj1.free();
- obj2.free();
- obj3.free();
return r;
}
@@ -1709,8 +1645,8 @@ void XRef::markUnencrypted(Object *obj) {
{
Array *array = obj->getArray();
for (int i = 0; i < array->getLength(); i++) {
- markUnencrypted(array->getNF(i, &obj1));
- obj1.free();
+ obj1 = array->getNF(i);
+ markUnencrypted(&obj1);
}
break;
}
@@ -1725,8 +1661,8 @@ void XRef::markUnencrypted(Object *obj) {
dict = obj->getDict();
}
for (int i = 0; i < dict->getLength(); i++) {
- markUnencrypted(dict->getValNF(i, &obj1));
- obj1.free();
+ obj1 = dict->getValNF(i);
+ markUnencrypted(&obj1);
}
break;
}
@@ -1737,9 +1673,8 @@ void XRef::markUnencrypted(Object *obj) {
if (e->getFlag(XRefEntry::Unencrypted))
return; // We've already been here: prevent infinite recursion
e->setFlag(XRefEntry::Unencrypted, gTrue);
- fetch(ref.num, ref.gen, &obj1);
+ obj1 = fetch(ref.num, ref.gen);
markUnencrypted(&obj1);
- obj1.free();
break;
}
default:
@@ -1783,19 +1718,16 @@ void XRef::scanSpecialFlags() {
}
// Mark objects referred from the Encrypt dict as Unencrypted
- Object obj;
- markUnencrypted(trailerDict.dictLookupNF("Encrypt", &obj));
- obj.free();
+ Object obj = trailerDict.dictLookupNF("Encrypt");
+ markUnencrypted();
}
void XRef::markUnencrypted() {
// Mark objects referred from the Encrypt dict as Unencrypted
- Object obj;
- trailerDict.dictLookupNF("Encrypt", &obj);
+ Object obj = trailerDict.dictLookupNF("Encrypt");
if (obj.isRef()) {
XRefEntry *e = getEntry(obj.getRefNum());
e->setFlag(XRefEntry::Unencrypted, gTrue);
}
- obj.free();
}