summaryrefslogtreecommitdiff
path: root/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2024-02-10 06:55:23 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2024-02-10 06:55:23 +0000
commit0357cc55904fda095727bb30f07b68dbf3439f8e (patch)
tree4dfe670d69c9d538606e6d49fe29b506c05e5975 /Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc
parent28c5129fe7864e1005edc90cf737372ba1bc78c7 (diff)
xpdf 4.05
git-svn-id: svn://tug.org/texlive/trunk@69765 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc')
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc282
1 files changed, 236 insertions, 46 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc
index ddcbad55f07..7a9b0701ca3 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Catalog.cc
@@ -8,10 +8,6 @@
#include <aconf.h>
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
#include <string.h>
#include <stddef.h>
#include <limits.h>
@@ -526,7 +522,10 @@ GBool Catalog::readPageTree(Object *catDict) {
// because other code tries to fetch pages 1 through n.
// In both cases: ignore the given page count and scan the tree
// instead.
- numPages = countPageTree(&topPagesObj);
+ char *touchedObjs = (char *)gmalloc(xref->getNumObjects());
+ memset(touchedObjs, 0, xref->getNumObjects());
+ numPages = countPageTree(&topPagesRef, touchedObjs);
+ gfree(touchedObjs);
}
} else {
// assume we got a Page node instead of a Pages node
@@ -553,30 +552,53 @@ GBool Catalog::readPageTree(Object *catDict) {
return gTrue;
}
-int Catalog::countPageTree(Object *pagesObj) {
- Object kids, kid;
- int n, n2, i;
-
- if (!pagesObj->isDict()) {
+int Catalog::countPageTree(Object *pagesNodeRef, char *touchedObjs) {
+ // check for invalid reference
+ if (pagesNodeRef->isRef() &&
+ (pagesNodeRef->getRefNum() < 0 ||
+ pagesNodeRef->getRefNum() >= xref->getNumObjects())) {
return 0;
}
- if (pagesObj->dictLookup("Kids", &kids)->isArray()) {
- n = 0;
- for (i = 0; i < kids.arrayGetLength(); ++i) {
- kids.arrayGet(i, &kid);
- n2 = countPageTree(&kid);
- if (n2 < INT_MAX - n) {
- n += n2;
- } else {
- error(errSyntaxError, -1, "Page tree contains too many pages");
- n = INT_MAX;
- }
- kid.free();
+
+ // check for a page tree loop; fetch the node object
+ Object pagesNode;
+ if (pagesNodeRef->isRef()) {
+ if (touchedObjs[pagesNodeRef->getRefNum()]) {
+ error(errSyntaxError, -1, "Loop in Pages tree");
+ return 0;
}
+ touchedObjs[pagesNodeRef->getRefNum()] = 1;
+ xref->fetch(pagesNodeRef->getRefNum(), pagesNodeRef->getRefGen(),
+ &pagesNode);
} else {
- n = 1;
+ pagesNodeRef->copy(&pagesNode);
+ }
+
+ // count the subtree
+ int n = 0;
+ if (pagesNode.isDict()) {
+ Object kids;
+ if (pagesNode.dictLookup("Kids", &kids)->isArray()) {
+ for (int i = 0; i < kids.arrayGetLength(); ++i) {
+ Object kid;
+ kids.arrayGetNF(i, &kid);
+ int n2 = countPageTree(&kid, touchedObjs);
+ if (n2 < INT_MAX - n) {
+ n += n2;
+ } else {
+ error(errSyntaxError, -1, "Page tree contains too many pages");
+ n = INT_MAX;
+ }
+ kid.free();
+ }
+ } else {
+ n = 1;
+ }
+ kids.free();
}
- kids.free();
+
+ pagesNode.free();
+
return n;
}
@@ -738,37 +760,55 @@ void Catalog::readEmbeddedFileList(Dict *catDict) {
Object obj1, obj2;
char *touchedObjs;
+ touchedObjs = (char *)gmalloc(xref->getNumObjects());
+ memset(touchedObjs, 0, xref->getNumObjects());
+
// read the embedded file name tree
if (catDict->lookup("Names", &obj1)->isDict()) {
- if (obj1.dictLookup("EmbeddedFiles", &obj2)->isDict()) {
- readEmbeddedFileTree(&obj2);
- }
+ obj1.dictLookupNF("EmbeddedFiles", &obj2);
+ readEmbeddedFileTree(&obj2, touchedObjs);
obj2.free();
}
obj1.free();
// look for file attachment annotations
- touchedObjs = (char *)gmalloc(xref->getNumObjects());
- memset(touchedObjs, 0, xref->getNumObjects());
readFileAttachmentAnnots(catDict->lookupNF("Pages", &obj1), touchedObjs);
obj1.free();
+
gfree(touchedObjs);
}
-void Catalog::readEmbeddedFileTree(Object *node) {
- Object kidsObj, kidObj;
+void Catalog::readEmbeddedFileTree(Object *nodeRef, char *touchedObjs) {
+ Object node, kidsObj, kidObj;
Object namesObj, nameObj, fileSpecObj;
int i;
- if (node->dictLookup("Kids", &kidsObj)->isArray()) {
+ // check for an object loop
+ if (nodeRef->isRef()) {
+ if (nodeRef->getRefNum() < 0 ||
+ nodeRef->getRefNum() >= xref->getNumObjects() ||
+ touchedObjs[nodeRef->getRefNum()]) {
+ return;
+ }
+ touchedObjs[nodeRef->getRefNum()] = 1;
+ xref->fetch(nodeRef->getRefNum(), nodeRef->getRefGen(), &node);
+ } else {
+ nodeRef->copy(&node);
+ }
+
+ if (!node.isDict()) {
+ node.free();
+ return;
+ }
+
+ if (node.dictLookup("Kids", &kidsObj)->isArray()) {
for (i = 0; i < kidsObj.arrayGetLength(); ++i) {
- if (kidsObj.arrayGet(i, &kidObj)->isDict()) {
- readEmbeddedFileTree(&kidObj);
- }
+ kidsObj.arrayGetNF(i, &kidObj);
+ readEmbeddedFileTree(&kidObj, touchedObjs);
kidObj.free();
}
} else {
- if (node->dictLookup("Names", &namesObj)->isArray()) {
+ if (node.dictLookup("Names", &namesObj)->isArray()) {
for (i = 0; i+1 < namesObj.arrayGetLength(); ++i) {
namesObj.arrayGet(i, &nameObj);
namesObj.arrayGet(i+1, &fileSpecObj);
@@ -780,6 +820,8 @@ void Catalog::readEmbeddedFileTree(Object *node) {
namesObj.free();
}
kidsObj.free();
+
+ node.free();
}
void Catalog::readFileAttachmentAnnots(Object *pageNodeRef,
@@ -788,8 +830,9 @@ void Catalog::readFileAttachmentAnnots(Object *pageNodeRef,
int i;
// check for an invalid object reference (e.g., in a damaged PDF file)
- if (pageNodeRef->getRefNum() < 0 ||
- pageNodeRef->getRefNum() >= xref->getNumObjects()) {
+ if (pageNodeRef->isRef() &&
+ (pageNodeRef->getRefNum() < 0 ||
+ pageNodeRef->getRefNum() >= xref->getNumObjects())) {
return;
}
@@ -901,10 +944,14 @@ Object *Catalog::getEmbeddedFileStreamObj(int idx, Object *strObj) {
void Catalog::readPageLabelTree(Object *root) {
PageLabelNode *label0, *label1;
+ char *touchedObjs;
int i;
+ touchedObjs = (char *)gmalloc(xref->getNumObjects());
+ memset(touchedObjs, 0, xref->getNumObjects());
pageLabels = new GList();
- readPageLabelTree2(root);
+ readPageLabelTree2(root, touchedObjs);
+ gfree(touchedObjs);
if (pageLabels->getLength() == 0) {
deleteGList(pageLabels, PageLabelNode);
@@ -922,15 +969,29 @@ void Catalog::readPageLabelTree(Object *root) {
label0->lastPage = numPages;
}
-void Catalog::readPageLabelTree2(Object *node) {
- Object nums, num, labelObj, kids, kid;
+void Catalog::readPageLabelTree2(Object *nodeRef, char *touchedObjs) {
+ Object node, nums, num, labelObj, kids, kid;
int i;
- if (!node->isDict()) {
+ // check for an object loop
+ if (nodeRef->isRef()) {
+ if (nodeRef->getRefNum() < 0 ||
+ nodeRef->getRefNum() >= xref->getNumObjects() ||
+ touchedObjs[nodeRef->getRefNum()]) {
+ return;
+ }
+ touchedObjs[nodeRef->getRefNum()] = 1;
+ xref->fetch(nodeRef->getRefNum(), nodeRef->getRefGen(), &node);
+ } else {
+ nodeRef->copy(&node);
+ }
+
+ if (!node.isDict()) {
+ node.free();
return;
}
- if (node->dictLookup("Nums", &nums)->isArray()) {
+ if (node.dictLookup("Nums", &nums)->isArray()) {
for (i = 0; i < nums.arrayGetLength() - 1; i += 2) {
if (nums.arrayGet(i, &num)->isInt()) {
if (nums.arrayGet(i+1, &labelObj)->isDict()) {
@@ -944,14 +1005,16 @@ void Catalog::readPageLabelTree2(Object *node) {
}
nums.free();
- if (node->dictLookup("Kids", &kids)->isArray()) {
+ if (node.dictLookup("Kids", &kids)->isArray()) {
for (i = 0; i < kids.arrayGetLength(); ++i) {
- kids.arrayGet(i, &kid);
- readPageLabelTree2(&kid);
+ kids.arrayGetNF(i, &kid);
+ readPageLabelTree2(&kid, touchedObjs);
kid.free();
}
}
kids.free();
+
+ node.free();
}
TextString *Catalog::getPageLabel(int pageNum) {
@@ -1195,3 +1258,130 @@ GBool Catalog::convertPageLabelToInt(TextString *pageLabel, int prefixLength,
}
return gFalse;
}
+
+GBool Catalog::usesJavaScript() {
+ Object catDict;
+ if (!xref->getCatalog(&catDict)->isDict()) {
+ catDict.free();
+ return gFalse;
+ }
+
+ GBool usesJS = gFalse;
+
+ // check for Catalog.Names.JavaScript
+ Object namesObj;
+ if (catDict.dictLookup("Names", &namesObj)->isDict()) {
+ Object jsNamesObj;
+ namesObj.dictLookup("JavaScript", &jsNamesObj);
+ if (jsNamesObj.isDict()) {
+ usesJS = gTrue;
+ }
+ jsNamesObj.free();
+ }
+ namesObj.free();
+
+ // look for JavaScript actionas in Page.AA
+ if (!usesJS) {
+ char *touchedObjs = (char *)gmalloc(xref->getNumObjects());
+ memset(touchedObjs, 0, xref->getNumObjects());
+ Object pagesObj;
+ usesJS = scanPageTreeForJavaScript(catDict.dictLookupNF("Pages", &pagesObj),
+ touchedObjs);
+ pagesObj.free();
+ gfree(touchedObjs);
+ }
+
+ catDict.free();
+
+ return usesJS;
+}
+
+GBool Catalog::scanPageTreeForJavaScript(Object *pageNodeRef,
+ char *touchedObjs) {
+ // check for an invalid object reference (e.g., in a damaged PDF file)
+ if (pageNodeRef->isRef() &&
+ (pageNodeRef->getRefNum() < 0 ||
+ pageNodeRef->getRefNum() >= xref->getNumObjects())) {
+ return gFalse;
+ }
+
+ // check for a page tree loop
+ Object pageNode;
+ if (pageNodeRef->isRef()) {
+ if (touchedObjs[pageNodeRef->getRefNum()]) {
+ return gFalse;
+ }
+ touchedObjs[pageNodeRef->getRefNum()] = 1;
+ xref->fetch(pageNodeRef->getRefNum(), pageNodeRef->getRefGen(), &pageNode);
+ } else {
+ pageNodeRef->copy(&pageNode);
+ }
+
+ // scan the page tree node
+ GBool usesJS = gFalse;
+ if (pageNode.isDict()) {
+ Object kids;
+ if (pageNode.dictLookup("Kids", &kids)->isArray()) {
+ for (int i = 0; i < kids.arrayGetLength() && !usesJS; ++i) {
+ Object kid;
+ if (scanPageTreeForJavaScript(kids.arrayGetNF(i, &kid), touchedObjs)) {
+ usesJS = gTrue;
+ }
+ kid.free();
+ }
+ } else {
+
+ // scan Page.AA
+ Object pageAA;
+ if (pageNode.dictLookup("AA", &pageAA)->isDict()) {
+ if (scanAAForJavaScript(&pageAA)) {
+ usesJS = gTrue;
+ }
+ }
+ pageAA.free();
+
+ // scanPage.Annots
+ if (!usesJS) {
+ Object annots;
+ if (pageNode.dictLookup("Annots", &annots)->isArray()) {
+ for (int i = 0; i < annots.arrayGetLength() && !usesJS; ++i) {
+ Object annot;
+ if (annots.arrayGet(i, &annot)->isDict()) {
+ Object annotAA;
+ if (annot.dictLookup("AA", &annotAA)->isDict()) {
+ if (scanAAForJavaScript(&annotAA)) {
+ usesJS = gTrue;
+ }
+ }
+ annotAA.free();
+ }
+ annot.free();
+ }
+ }
+ annots.free();
+ }
+ }
+ kids.free();
+ }
+
+ pageNode.free();
+
+ return usesJS;
+}
+
+GBool Catalog::scanAAForJavaScript(Object *aaObj) {
+ GBool usesJS = gFalse;
+ for (int i = 0; i < aaObj->dictGetLength() && !usesJS; ++i) {
+ Object action;
+ if (aaObj->dictGetVal(i, &action)->isDict()) {
+ Object js;
+ if (!action.dictLookupNF("JS", &js)->isNull()) {
+ usesJS = gTrue;
+ }
+ js.free();
+ }
+ action.free();
+ }
+ return usesJS;
+}
+