[poppler] poppler/Form.cc poppler/Form.h

Albert Astals Cid aacid at kemper.freedesktop.org
Sat Nov 20 11:15:01 PST 2010


 poppler/Form.cc |   88 +++++++++++++++++++++++++++++++-------------------------
 poppler/Form.h  |   14 +++++---
 2 files changed, 58 insertions(+), 44 deletions(-)

New commits:
commit 555fa897b275ca7195f22a727b049c8c4f2d74cd
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sat Nov 20 19:14:38 2010 +0000

    Detect loops in FormField creation

diff --git a/poppler/Form.cc b/poppler/Form.cc
index 78e46ef..74e8d90 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -759,7 +759,7 @@ FormWidgetSignature::FormWidgetSignature(XRef *xrefA, Object *aobj, unsigned num
 // FormField
 //========================================================================
 
-FormField::FormField(XRef* xrefA, Object *aobj, const Ref& aref, FormFieldType ty) 
+FormField::FormField(XRef* xrefA, Object *aobj, const Ref& aref, std::set<int> *usedParents, FormFieldType ty)
 {
   xref = xrefA;
   aobj->copy(&obj);
@@ -789,32 +789,43 @@ FormField::FormField(XRef* xrefA, Object *aobj, const Ref& aref, FormFieldType t
       }
       Object childRef;
       array->getNF(i, &childRef);
-      //field child
-      if (dict->lookup ("FT", &obj3)->isName()) {
-        // If I'm not a generic container field and my children
-        // are widgets, create widgets for them
-        Object obj4;
-
-        if (obj2.dictLookup("Subtype",&obj4)->isName()) {
-          _createWidget(&obj2, childRef.getRef());
-        }
-        obj4.free();
-      } else if(obj2.dictLookup("FT", &obj3)->isName() || obj2.dictLookup("Kids", &obj3)->isArray()) {
-        if(terminal) error(-1, "Field can't have both Widget AND Field as kids\n");
+      if (childRef.isRef()) {
+        const Ref ref = childRef.getRef();
+        if (usedParents->find(ref.num) == usedParents->end()) {
+          //field child
+          if (dict->lookup ("FT", &obj3)->isName()) {
+            // If I'm not a generic container field and my children
+            // are widgets, create widgets for them
+            Object obj4;
+
+            if (obj2.dictLookup("Subtype",&obj4)->isName()) {
+              _createWidget(&obj2, childRef.getRef());
+            }
+            obj4.free();
+          } else if(obj2.dictLookup("FT", &obj3)->isName() || obj2.dictLookup("Kids", &obj3)->isArray()) {
+            std::set<int> usedParentsAux = *usedParents;
+            usedParentsAux.insert(ref.num);
+            if(terminal) error(-1, "Field can't have both Widget AND Field as kids\n");
 
-        numChildren++;
-        children = (FormField**)greallocn(children, numChildren, sizeof(FormField*));
+            numChildren++;
+            children = (FormField**)greallocn(children, numChildren, sizeof(FormField*));
 
-        obj3.free();
-        children[numChildren-1] = Form::createFieldFromDict (&obj2, xrefA, childRef.getRef());
-      }
-      // 1 - we will handle 'collapsed' fields (field + annot in the same dict)
-      // as if the annot was in the Kids array of the field
-      else if (obj2.dictLookup("Subtype",&obj3)->isName()) {
-        _createWidget(&obj2, childRef.getRef());
+            obj3.free();
+            children[numChildren-1] = Form::createFieldFromDict (&obj2, xrefA, childRef.getRef(), &usedParentsAux);
+          }
+          // 1 - we will handle 'collapsed' fields (field + annot in the same dict)
+          // as if the annot was in the Kids array of the field
+          else if (obj2.dictLookup("Subtype",&obj3)->isName()) {
+            _createWidget(&obj2, childRef.getRef());
+          }
+          obj3.free();
+        } else {
+          error(-1, "Found loop in FormField creation");
+        }
+      } else {
+        error(-1, "FormField child is not a Ref as expected");
       }
       obj2.free();
-      obj3.free();
     }
   }
   obj1.free();
@@ -926,8 +937,8 @@ FormWidget* FormField::findWidgetByRef (Ref aref)
 //------------------------------------------------------------------------
 // FormFieldButton
 //------------------------------------------------------------------------
-FormFieldButton::FormFieldButton(XRef *xrefA, Object *aobj, const Ref& ref) 
-	: FormField(xrefA, aobj, ref, formButton)
+FormFieldButton::FormFieldButton(XRef *xrefA, Object *aobj, const Ref& ref, std::set<int> *usedParents)
+	: FormField(xrefA, aobj, ref, usedParents, formButton)
 {
   Dict* dict = obj.getDict();
   active_child = -1;
@@ -1020,8 +1031,8 @@ FormFieldButton::~FormFieldButton()
 //------------------------------------------------------------------------
 // FormFieldText
 //------------------------------------------------------------------------
-FormFieldText::FormFieldText(XRef *xrefA, Object *aobj, const Ref& ref) 
-	: FormField(xrefA, aobj, ref, formText)
+FormFieldText::FormFieldText(XRef *xrefA, Object *aobj, const Ref& ref, std::set<int> *usedParents)
+	: FormField(xrefA, aobj, ref, usedParents, formText)
 {
   Dict* dict = obj.getDict();
   Object obj1;
@@ -1077,8 +1088,8 @@ FormFieldText::~FormFieldText()
 //------------------------------------------------------------------------
 // FormFieldChoice
 //------------------------------------------------------------------------
-FormFieldChoice::FormFieldChoice(XRef *xrefA, Object *aobj, const Ref& ref) 
-	: FormField(xrefA, aobj, ref, formChoice)
+FormFieldChoice::FormFieldChoice(XRef *xrefA, Object *aobj, const Ref& ref, std::set<int> *usedParents)
+	: FormField(xrefA, aobj, ref, usedParents, formChoice)
 {
   numChoices = 0;
   choices = NULL;
@@ -1171,8 +1182,8 @@ void FormFieldChoice::_createChoicesTab ()
 //------------------------------------------------------------------------
 // FormFieldSignature
 //------------------------------------------------------------------------
-FormFieldSignature::FormFieldSignature(XRef *xrefA, Object *dict, const Ref& ref)
-	: FormField(xrefA, dict, ref, formSignature)
+FormFieldSignature::FormFieldSignature(XRef *xrefA, Object *dict, const Ref& ref, std::set<int> *usedParents)
+	: FormField(xrefA, dict, ref, usedParents, formSignature)
 {
 }
 
@@ -1228,7 +1239,8 @@ Form::Form(XRef *xrefA, Object* acroFormA)
         rootFields = (FormField**)greallocn(rootFields,size,sizeof(FormField*));
       }
 
-      rootFields[numFields++] = createFieldFromDict (&obj2, xrefA, oref.getRef());
+      std::set<int> usedParents;
+      rootFields[numFields++] = createFieldFromDict (&obj2, xrefA, oref.getRef(), &usedParents);
 
       obj2.free();
       oref.free();
@@ -1285,21 +1297,21 @@ Object *Form::fieldLookup(Dict *field, char *key, Object *obj) {
   return ::fieldLookup(field, key, obj, &usedParents);
 }
 
-FormField *Form::createFieldFromDict (Object* obj, XRef *xrefA, const Ref& pref)
+FormField *Form::createFieldFromDict (Object* obj, XRef *xrefA, const Ref& pref, std::set<int> *usedParents)
 {
     Object obj2;
     FormField *field;
 
     if (Form::fieldLookup(obj->getDict (), "FT", &obj2)->isName("Btn")) {
-      field = new FormFieldButton(xrefA, obj, pref);
+      field = new FormFieldButton(xrefA, obj, pref, usedParents);
     } else if (obj2.isName("Tx")) {
-      field = new FormFieldText(xrefA, obj, pref);
+      field = new FormFieldText(xrefA, obj, pref, usedParents);
     } else if (obj2.isName("Ch")) {
-      field = new FormFieldChoice(xrefA, obj, pref);
+      field = new FormFieldChoice(xrefA, obj, pref, usedParents);
     } else if (obj2.isName("Sig")) {
-      field = new FormFieldSignature(xrefA, obj, pref);
+      field = new FormFieldSignature(xrefA, obj, pref, usedParents);
     } else { //we don't have an FT entry => non-terminal field
-      field = new FormField(xrefA, obj, pref);
+      field = new FormField(xrefA, obj, pref, usedParents);
     }
     obj2.free();
     
diff --git a/poppler/Form.h b/poppler/Form.h
index eb76fbb..106c556 100644
--- a/poppler/Form.h
+++ b/poppler/Form.h
@@ -20,6 +20,8 @@
 
 #include "Object.h"
 
+#include <set>
+
 class GooString;
 class Array;
 class Dict;
@@ -256,7 +258,7 @@ protected:
 
 class FormField {
 public:
-  FormField(XRef* xrefa, Object *aobj, const Ref& aref, FormFieldType t=formUndef);
+  FormField(XRef* xrefa, Object *aobj, const Ref& aref, std::set<int> *usedParents, FormFieldType t=formUndef);
 
   virtual ~FormField();
 
@@ -301,7 +303,7 @@ private:
 
 class FormFieldButton: public FormField {
 public:
-  FormFieldButton(XRef *xrefA, Object *dict, const Ref& ref);
+  FormFieldButton(XRef *xrefA, Object *dict, const Ref& ref, std::set<int> *usedParents);
 
   FormButtonType getButtonType () { return btype; }
 
@@ -326,7 +328,7 @@ protected:
 
 class FormFieldText: public FormField {
 public:
-  FormFieldText(XRef *xrefA, Object *dict, const Ref& ref);
+  FormFieldText(XRef *xrefA, Object *dict, const Ref& ref, std::set<int> *usedParents);
   
   GooString* getContent () { return content; }
   GooString* getContentCopy ();
@@ -360,7 +362,7 @@ protected:
 
 class FormFieldChoice: public FormField {
 public:
-  FormFieldChoice(XRef *xrefA, Object *aobj, const Ref& ref);
+  FormFieldChoice(XRef *xrefA, Object *aobj, const Ref& ref, std::set<int> *usedParents);
 
   virtual ~FormFieldChoice();
 
@@ -423,7 +425,7 @@ protected:
 
 class FormFieldSignature: public FormField {
 public:
-  FormFieldSignature(XRef *xrefA, Object *dict, const Ref& ref);
+  FormFieldSignature(XRef *xrefA, Object *dict, const Ref& ref, std::set<int> *usedParents);
 
   virtual ~FormFieldSignature();
 };
@@ -445,7 +447,7 @@ public:
   
   /* Creates a new Field of the type specified in obj's dict.
      used in Form::Form and FormField::FormField */
-  static FormField *createFieldFromDict (Object* obj, XRef *xref, const Ref& aref);
+  static FormField *createFieldFromDict (Object* obj, XRef *xref, const Ref& aref, std::set<int> *usedParents);
 
   Object *getObj () const { return acroForm; }
   GBool getNeedAppearances () const { return needAppearances; }


More information about the poppler mailing list