XRef.cc (xpdf-4.03) | : | XRef.cc (xpdf-4.04) | ||
---|---|---|---|---|
skipping to change at line 302 | skipping to change at line 302 | |||
//------------------------------------------------------------------------ | //------------------------------------------------------------------------ | |||
XRef::XRef(BaseStream *strA, GBool repair) { | XRef::XRef(BaseStream *strA, GBool repair) { | |||
GFileOffset pos; | GFileOffset pos; | |||
Object obj; | Object obj; | |||
XRefPosSet *posSet; | XRefPosSet *posSet; | |||
int i; | int i; | |||
ok = gTrue; | ok = gTrue; | |||
errCode = errNone; | errCode = errNone; | |||
repaired = gFalse; | ||||
size = 0; | size = 0; | |||
last = -1; | last = -1; | |||
entries = NULL; | entries = NULL; | |||
lastStartxrefPos = 0; | lastStartxrefPos = 0; | |||
xrefTablePos = NULL; | xrefTablePos = NULL; | |||
xrefTablePosLen = 0; | xrefTablePosLen = 0; | |||
streamEnds = NULL; | streamEnds = NULL; | |||
streamEndsLen = 0; | streamEndsLen = 0; | |||
for (i = 0; i < objStrCacheSize; ++i) { | for (i = 0; i < objStrCacheSize; ++i) { | |||
objStrs[i] = NULL; | objStrs[i] = NULL; | |||
skipping to change at line 339 | skipping to change at line 340 | |||
str = strA; | str = strA; | |||
start = str->getStart(); | start = str->getStart(); | |||
// if the 'repair' flag is set, try to reconstruct the xref table | // if the 'repair' flag is set, try to reconstruct the xref table | |||
if (repair) { | if (repair) { | |||
if (!(ok = constructXRef())) { | if (!(ok = constructXRef())) { | |||
errCode = errDamaged; | errCode = errDamaged; | |||
return; | return; | |||
} | } | |||
repaired = gTrue; | ||||
// if the 'repair' flag is not set, read the xref table | // if the 'repair' flag is not set, read the xref table | |||
} else { | } else { | |||
// read the trailer | // read the trailer | |||
pos = getStartXref(); | pos = getStartXref(); | |||
if (pos == 0) { | if (pos == 0) { | |||
errCode = errDamaged; | errCode = errDamaged; | |||
ok = gFalse; | ok = gFalse; | |||
return; | return; | |||
skipping to change at line 515 | skipping to change at line 517 | |||
return gFalse; | return gFalse; | |||
} | } | |||
GBool XRef::readXRefTable(GFileOffset *pos, int offset, XRefPosSet *posSet) { | GBool XRef::readXRefTable(GFileOffset *pos, int offset, XRefPosSet *posSet) { | |||
XRefEntry entry; | XRefEntry entry; | |||
Parser *parser; | Parser *parser; | |||
Object obj, obj2; | Object obj, obj2; | |||
char buf[6]; | char buf[6]; | |||
GFileOffset off, pos2; | GFileOffset off, pos2; | |||
GBool more; | GBool more; | |||
int first, n, newSize, gen, i, c; | int first, n, digit, newSize, gen, i, c; | |||
str->setPos(start + *pos + offset); | str->setPos(start + *pos + offset); | |||
while (1) { | while (1) { | |||
do { | do { | |||
c = str->getChar(); | c = str->getChar(); | |||
} while (Lexer::isSpace(c)); | } while (Lexer::isSpace(c)); | |||
if (c == 't') { | if (c == 't') { | |||
if (str->getBlock(buf, 6) != 6 || memcmp(buf, "railer", 6)) { | if (str->getBlock(buf, 6) != 6 || memcmp(buf, "railer", 6)) { | |||
goto err1; | goto err1; | |||
} | } | |||
break; | break; | |||
} | } | |||
if (c < '0' || c > '9') { | if (c < '0' || c > '9') { | |||
goto err1; | goto err1; | |||
} | } | |||
first = 0; | first = 0; | |||
do { | do { | |||
first = (first * 10) + (c - '0'); | digit = c - '0'; | |||
if (first > (INT_MAX - digit) / 10) { | ||||
goto err1; | ||||
} | ||||
first = (first * 10) + digit; | ||||
c = str->getChar(); | c = str->getChar(); | |||
} while (c >= '0' && c <= '9'); | } while (c >= '0' && c <= '9'); | |||
if (!Lexer::isSpace(c)) { | if (!Lexer::isSpace(c)) { | |||
goto err1; | goto err1; | |||
} | } | |||
do { | do { | |||
c = str->getChar(); | c = str->getChar(); | |||
} while (Lexer::isSpace(c)); | } while (Lexer::isSpace(c)); | |||
n = 0; | n = 0; | |||
do { | do { | |||
n = (n * 10) + (c - '0'); | digit = c - '0'; | |||
if (n > (INT_MAX - digit) / 10) { | ||||
goto err1; | ||||
} | ||||
n = (n * 10) + digit; | ||||
c = str->getChar(); | c = str->getChar(); | |||
} while (c >= '0' && c <= '9'); | } while (c >= '0' && c <= '9'); | |||
if (!Lexer::isSpace(c)) { | if (!Lexer::isSpace(c)) { | |||
goto err1; | goto err1; | |||
} | } | |||
if (first < 0 || n < 0 || first > INT_MAX - n) { | if (first > INT_MAX - n) { | |||
goto err1; | goto err1; | |||
} | } | |||
if (first + n > size) { | if (first + n > size) { | |||
for (newSize = size ? 2 * size : 1024; | for (newSize = size ? 2 * size : 1024; | |||
first + n > newSize && newSize > 0; | first + n > newSize && newSize > 0; | |||
newSize <<= 1) ; | newSize <<= 1) ; | |||
if (newSize < 0) { | if (newSize < 0) { | |||
goto err1; | goto err1; | |||
} | } | |||
entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); | entries = (XRefEntry *)greallocn(entries, newSize, sizeof(XRefEntry)); | |||
skipping to change at line 825 | skipping to change at line 835 | |||
} | } | |||
if (offset < 0 || offset > GFILEOFFSET_MAX) { | if (offset < 0 || offset > GFILEOFFSET_MAX) { | |||
return gFalse; | return gFalse; | |||
} | } | |||
for (gen = 0, j = 0; j < w[2]; ++j) { | for (gen = 0, j = 0; j < w[2]; ++j) { | |||
if ((c = xrefStr->getChar()) == EOF) { | if ((c = xrefStr->getChar()) == EOF) { | |||
return gFalse; | return gFalse; | |||
} | } | |||
gen = (gen << 8) + c; | gen = (gen << 8) + c; | |||
} | } | |||
if (gen < 0 || gen > INT_MAX) { | // some PDF generators include a free entry with gen=0xffffffff | |||
if ((gen < 0 || gen > INT_MAX) && type != 0) { | ||||
return gFalse; | return gFalse; | |||
} | } | |||
if (entries[i].offset == (GFileOffset)-1) { | if (entries[i].offset == (GFileOffset)-1) { | |||
switch (type) { | switch (type) { | |||
case 0: | case 0: | |||
entries[i].offset = (GFileOffset)offset; | entries[i].offset = (GFileOffset)offset; | |||
entries[i].gen = (int)gen; | entries[i].gen = (int)gen; | |||
entries[i].type = xrefEntryFree; | entries[i].type = xrefEntryFree; | |||
break; | break; | |||
case 1: | case 1: | |||
skipping to change at line 911 | skipping to change at line 922 | |||
} else if (startOfLine && *p >= '0' && *p <= '9') { | } else if (startOfLine && *p >= '0' && *p <= '9') { | |||
p = constructObjectEntry(p, (GFileOffset)(bufPos + (p - buf)), | p = constructObjectEntry(p, (GFileOffset)(bufPos + (p - buf)), | |||
&lastObjNum); | &lastObjNum); | |||
startOfLine = gFalse; | startOfLine = gFalse; | |||
} else if (p[0] == '>' && p[1] == '>') { | } else if (p[0] == '>' && p[1] == '>') { | |||
p += 2; | p += 2; | |||
startOfLine = gFalse; | startOfLine = gFalse; | |||
// skip any PDF whitespace except for '\0' | // skip any PDF whitespace except for '\0' | |||
while (*p == '\t' || *p == '\n' || *p == '\x0c' || | while (*p == '\t' || *p == '\n' || *p == '\x0c' || | |||
*p == '\r' || *p == ' ') { | *p == '\r' || *p == ' ') { | |||
startOfLine = *p == '\n' || *p == '\r'; | if (*p == '\n' || *p == '\r') { | |||
startOfLine = gTrue; | ||||
} | ||||
++p; | ++p; | |||
} | } | |||
if (!strncmp(p, "stream", 6)) { | if (!strncmp(p, "stream", 6)) { | |||
if (lastObjNum >= 0) { | if (lastObjNum >= 0) { | |||
if (streamObjNumsLen == streamObjNumsSize) { | if (streamObjNumsLen == streamObjNumsSize) { | |||
streamObjNumsSize += 64; | streamObjNumsSize += 64; | |||
streamObjNums = (int *)greallocn(streamObjNums, streamObjNumsSize, | streamObjNums = (int *)greallocn(streamObjNums, streamObjNumsSize, | |||
sizeof(int)); | sizeof(int)); | |||
} | } | |||
streamObjNums[streamObjNumsLen++] = lastObjNum; | streamObjNums[streamObjNumsLen++] = lastObjNum; | |||
} | } | |||
p += 6; | p += 6; | |||
startOfLine = gFalse; | startOfLine = gFalse; | |||
} | } | |||
} else { | } else { | |||
startOfLine = *p == '\n' || *p == '\r'; | if (*p == '\n' || *p == '\r') { | |||
startOfLine = gTrue; | ||||
} else if (!Lexer::isSpace(*p & 0xff)) { | ||||
startOfLine = gFalse; | ||||
} | ||||
++p; | ++p; | |||
} | } | |||
} | } | |||
// read each stream object, check for xref or object stream | // read each stream object, check for xref or object stream | |||
for (int i = 0; i < streamObjNumsLen; ++i) { | for (int i = 0; i < streamObjNumsLen; ++i) { | |||
Object obj; | Object obj; | |||
fetch(streamObjNums[i], entries[streamObjNums[i]].gen, &obj); | fetch(streamObjNums[i], entries[streamObjNums[i]].gen, &obj); | |||
if (obj.isStream()) { | if (obj.isStream()) { | |||
Dict *dict = obj.streamGetDict(); | Dict *dict = obj.streamGetDict(); | |||
skipping to change at line 952 | skipping to change at line 969 | |||
} else if (type.isName("ObjStm")) { | } else if (type.isName("ObjStm")) { | |||
constructObjectStreamEntries(&obj, streamObjNums[i]); | constructObjectStreamEntries(&obj, streamObjNums[i]); | |||
} | } | |||
type.free(); | type.free(); | |||
} | } | |||
obj.free(); | obj.free(); | |||
} | } | |||
gfree(streamObjNums); | gfree(streamObjNums); | |||
// if the file is encrypted, then any objects fetched here will be | ||||
// incorrect (because decryption is not yet enabled), so clear the | ||||
// cache to avoid that problem | ||||
for (int i = 0; i < xrefCacheSize; ++i) { | ||||
if (cache[i].num >= 0) { | ||||
cache[i].obj.free(); | ||||
cache[i].num = -1; | ||||
} | ||||
} | ||||
if (rootNum < 0) { | if (rootNum < 0) { | |||
error(errSyntaxError, -1, "Couldn't find trailer dictionary"); | error(errSyntaxError, -1, "Couldn't find trailer dictionary"); | |||
return gFalse; | return gFalse; | |||
} | } | |||
return gTrue; | return gTrue; | |||
} | } | |||
// Attempt to construct a trailer dict at [pos] in the stream. | // Attempt to construct a trailer dict at [pos] in the stream. | |||
void XRef::constructTrailerDict(GFileOffset pos) { | void XRef::constructTrailerDict(GFileOffset pos) { | |||
Object newTrailerDict, obj; | Object newTrailerDict, obj; | |||
End of changes. 10 change blocks. | ||||
7 lines changed or deleted | 34 lines changed or added |