summaryrefslogtreecommitdiff
authorAlbert Astals Cid <aacid@kde.org>2010-09-21 18:19:27 (GMT)
committer Albert Astals Cid <aacid@kde.org>2010-09-21 18:19:27 (GMT)
commitd2578bd66129466b2dd114b6407c147598e09d2b (patch) (side-by-side diff)
tree3abaf72bc2fba70f1d5ff6b8ddab0a300fb1e8f1
parent2fe825deac055be82b220d0127169cb3d61387a8 (diff)
downloadpoppler-d2578bd66129466b2dd114b6407c147598e09d2b.zip
poppler-d2578bd66129466b2dd114b6407c147598e09d2b.tar.gz
Avoid loops in Form::fieldLookup
Fixes crash in broken pdf provided by Joel Voss of Leviathan Security Group
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--poppler/Dict.h3
-rw-r--r--poppler/Form.cc27
2 files changed, 27 insertions, 3 deletions
diff --git a/poppler/Dict.h b/poppler/Dict.h
index bb747d5..a76bc89 100644
--- a/poppler/Dict.h
+++ b/poppler/Dict.h
@@ -16,6 +16,7 @@
// Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
// Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
// Copyright (C) 2007-2008 Julien Rebetez <julienr@svn.gnome.org>
+// Copyright (C) 2010 Albert Astals Cid <aacid@kde.org>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -83,6 +84,8 @@ public:
// trailer dictionary, which is read before the xref table is
// parsed.
void setXRef(XRef *xrefA) { xref = xrefA; }
+
+ XRef *getXRef() { return xref; }
private:
diff --git a/poppler/Form.cc b/poppler/Form.cc
index 21ca672..ae9c509 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -22,6 +22,7 @@
#pragma implementation
#endif
+#include <set>
#include <stddef.h>
#include <string.h>
#include "goo/gmem.h"
@@ -1181,7 +1182,7 @@ Form::~Form() {
}
// Look up an inheritable field dictionary entry.
-Object *Form::fieldLookup(Dict *field, char *key, Object *obj) {
+static Object *fieldLookup(Dict *field, char *key, Object *obj, std::set<int> *usedParents) {
Dict *dict;
Object parent;
@@ -1190,8 +1191,23 @@ Object *Form::fieldLookup(Dict *field, char *key, Object *obj) {
return obj;
}
obj->free();
- if (dict->lookup("Parent", &parent)->isDict()) {
- fieldLookup(parent.getDict(), key, obj);
+ dict->lookupNF("Parent", &parent);
+ if (parent.isRef()) {
+ const Ref ref = parent.getRef();
+ if (usedParents->find(ref.num) == usedParents->end()) {
+ usedParents->insert(ref.num);
+
+ Object obj2;
+ parent.fetch(dict->getXRef(), &obj2);
+ if (obj2.isDict()) {
+ fieldLookup(obj2.getDict(), key, obj, usedParents);
+ } else {
+ obj->initNull();
+ }
+ obj2.free();
+ }
+ } else if (parent.isDict()) {
+ fieldLookup(parent.getDict(), key, obj, usedParents);
} else {
obj->initNull();
}
@@ -1199,6 +1215,11 @@ Object *Form::fieldLookup(Dict *field, char *key, Object *obj) {
return obj;
}
+Object *Form::fieldLookup(Dict *field, char *key, Object *obj) {
+ std::set<int> usedParents;
+ return ::fieldLookup(field, key, obj, &usedParents);
+}
+
FormField *Form::createFieldFromDict (Object* obj, XRef *xrefA, const Ref& pref)
{
Object obj2;