--- poppler/Form.cc.orig	2007-05-21 17:21:31.000000000 -0400
+++ poppler/Form.cc	2007-07-31 09:03:35.000000000 -0400
@@ -120,7 +120,7 @@
 
 FormWidget::~FormWidget()
 {
-
+  obj.free ();
 }
 
 int FormWidget::encodeID (unsigned pageNum, unsigned fieldNum)
@@ -149,10 +149,19 @@
 {
   if (siblingsID)
     gfree(siblingsID);
+  delete onStr;
+}
+
+FormButtonType FormWidgetButton::getButtonType () const
+{
+  return parent->getButtonType ();
 }
 
 void FormWidgetButton::setState (GBool astate, GBool calledByParent)
 {
+  //pushButtons don't have state
+  if (parent->getButtonType() == formButtonPush)
+    return;
   //the state modification may be denied by the parent. e.g we don't want to let the user put all combo boxes to false
   if (!calledByParent) { //avoid infinite recursion
     if (!parent->setState(childNum, astate)) {
@@ -162,13 +171,12 @@
   state = astate;
   //update appearance
   char *offStr = "Off";
-  Object *obj1 = new Object();
-  obj1->initName(state?onStr:offStr);
-  obj.getDict()->set("V", obj1);
-  obj1 = new Object();
-  obj1->initName(state?onStr:offStr);
+  Object obj1;
+  obj1.initName(state?getOnStr():offStr);
+  obj.getDict()->set("V", &obj1);
+  obj1.initName(state?getOnStr():offStr);
   //modify the Appearance State entry as well
-  obj.getDict()->set("AS", obj1);
+  obj.getDict()->set("AS", &obj1);
 
   //notify the xref about the update
   xref->setModifiedObject(&obj, ref);
@@ -203,7 +211,7 @@
             tmpDict2->getVal(j, &obj3);
             char *key = tmpDict2->getKey(j);
             if(strcmp(key, "Off")) { //if we don't have Off, we have the name of the "on" state
-              onStr = strdup(key);
+	      onStr = new GooString (key);
             }
             obj3.free();
           }
@@ -213,7 +221,7 @@
           Object obj3;
           tmpDict2->lookup("Length", &obj3);
           int c;
-          onStr = "D"; 
+          onStr = new GooString ("D"); 
         }
         obj2.free();
       }
@@ -226,10 +234,8 @@
     }
   }
 
-  if (dict->lookup("V", &obj1)->isName()) {
-    char *s = obj1.getName();
-    if(strcmp(s, "Off")) {
-      //state = gTrue;
+  if (Form::fieldLookup(dict, "V", &obj1)->isName()) {
+    if (strcmp (obj1.getName(), "Off") != 0) {
       setState(gTrue);
     }
   } else if (obj1.isArray()) { //handle the case where we have multiple choices
@@ -261,7 +267,7 @@
   Dict *dict = obj.getDict();
   Object obj1;
 
-  if (dict->lookup("V", &obj1)->isString()) {
+  if (Form::fieldLookup(dict, "V", &obj1)->isString()) {
     if (obj1.getString()->hasUnicodeMarker()) {
       if (obj1.getString()->getLength() <= 2) {
       } else {
@@ -275,6 +281,7 @@
         GooString* str1 = new GooString(tmp_str, tmp_length);
         parent->setContentCopy(str1);
         delete str1;
+	delete []tmp_str;
       }
     }
   }
@@ -332,6 +339,11 @@
   return parent->isReadOnly();
 }
 
+int FormWidgetText::getMaxLen () const
+{
+  return parent->getMaxLen ();
+}
+
 void FormWidgetText::setContent(GooString* new_content)
 {
   if (isReadOnly()) {
@@ -350,12 +362,11 @@
     
     GooString *cont = new GooString(new_content);
     parent->setContentCopy(cont);
-    Object *obj1 = new Object();
-    obj1->initString(cont);
-    obj.getDict()->set("V", obj1);
+    Object obj1;
+    obj1.initString(cont);
+    obj.getDict()->set("V", &obj1);
     //notify the xref about the update
     xref->setModifiedObject(&obj, ref);
-
   }
 }
 
@@ -406,7 +417,7 @@
   memset(tmpCurrentChoice, 0, sizeof(bool)*parent->getNumChoices());
 
   //find default choice
-  if (dict->lookup("V", &obj1)->isString()) {  
+  if (Form::fieldLookup(dict, "V", &obj1)->isString()) {
     for(int i=0; i<parent->getNumChoices(); i++) {
       if (parent->getChoice(i)->cmp(obj1.getString()) == 0) {
         tmpCurrentChoice[i] = true;
@@ -467,33 +478,33 @@
 
 void FormWidgetChoice::_updateV ()
 {
-  Object *obj1 = new Object();
+  Object obj1;
   //this is an editable combo-box with user-entered text
   if (hasEdit() && parent->getEditChoice()) { 
-    obj1->initString(new GooString(parent->getEditChoice()));
+    obj1.initString(new GooString(parent->getEditChoice()));
   } else {
     int numSelected = parent->getNumSelected();
     if (numSelected == 0) {
-      obj1->initString(new GooString(""));
+      obj1.initString(new GooString(""));
     } else if (numSelected == 1) {
       for(int i=0; i<parent->getNumChoices(); i++) {
         if (parent->isSelected(i)) {
-          obj1->initString(new GooString(parent->getExportVal(i)));
+          obj1.initString(new GooString(parent->getExportVal(i)));
           break;
         }
       }
     } else {
-      obj1->initArray(xref);
+      obj1.initArray(xref);
       for(int i=0; i<parent->getNumChoices(); i++) {
         if (parent->isSelected(i)) {
-          Object* obj2 = new Object();
-          obj2->initString(new GooString(parent->getExportVal(i)));
-          obj1->arrayAdd(obj2);
+          Object obj2;
+          obj2.initString(new GooString(parent->getExportVal(i)));
+          obj1.arrayAdd(&obj2);
         }
       }
     }
   }
-  obj.getDict()->set("V", obj1);
+  obj.getDict()->set("V", &obj1);
   //notify the xref about the update
   xref->setModifiedObject(&obj, ref);
 }
@@ -667,7 +678,16 @@
       array->get(i, &obj2);
       array->getNF(i, &childRef);
       //field child
-      if(obj2.dictLookup("FT", &obj3)->isName()) {
+      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()) {
         if(terminal) error(-1, "Field can't have both Widget AND Field as kids\n");
 
         numChildren++;
@@ -679,7 +699,7 @@
       // 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());       
+        _createWidget(&obj2, childRef.getRef());
       }
       obj2.free();
       obj3.free();
@@ -694,7 +714,7 @@
   obj1.free();
  
   //flags
-  if (dict->lookup("Ff", &obj1)->isInt()) {
+  if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
     int flags = obj1.getInt();
     if (flags & 0x2) { // 2 -> Required
       //TODO
@@ -704,18 +724,21 @@
     }
   }
   obj1.free();
-
 }
 
-/*FormField::FormField(FormField *dest)
-{
-  type = dest->type;
-}*/
-
 FormField::~FormField()
 {
-  if(children)
-    gfree(children);
+  if (!terminal) {
+    if(children) {
+      for (int i=0; i<numChildren; i++)
+        delete children[i];
+      gfree(children);
+    }
+  } else {
+    for (int i = 0; i < numChildren; ++i)
+      delete widgets[i];
+    gfree (widgets);
+  }
   obj.free();
 }
 
@@ -789,8 +812,9 @@
 
   Object obj1;
   btype = formButtonCheck; 
-  if (dict->lookup("Ff", &obj1)->isInt()) {
+  if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
     int flags = obj1.getInt();
+    
     if (flags & 0x10000) { // 17 -> push button
       btype = formButtonPush;
     } else if (flags & 0x8000) { // 16 -> radio button
@@ -803,18 +827,23 @@
       error(-1, "FormFieldButton:: radiosInUnison flag unimplemented, please report a bug with a testcase\n");
     } 
   }
-  obj1.free();
 }
 
 void FormFieldButton::fillChildrenSiblingsID()
 {
-  for(int i=0; i<numChildren; i++) {
-    FormWidgetButton *btn = static_cast<FormWidgetButton*>(widgets[i]);
-    btn->setNumSiblingsID(numChildren-1);
-    for(int j=0, counter=0; j<numChildren; j++) {
-      if (i == j) continue;
-      btn->setSiblingsID(counter, widgets[j]->getID());
-      counter++;
+  if (!terminal) {
+    for(int i=0; i<numChildren; i++) {
+      children[i]->fillChildrenSiblingsID();
+    }
+  } else {
+    for(int i=0; i<numChildren; i++) {
+      FormWidgetButton *btn = static_cast<FormWidgetButton*>(widgets[i]);
+      btn->setNumSiblingsID(numChildren-1);
+      for(int j=0, counter=0; j<numChildren; j++) {
+        if (i == j) continue;
+        btn->setSiblingsID(counter, widgets[j]->getID());
+        counter++;
+      }
     }
   }
 }
@@ -825,8 +854,10 @@
     error(-1, "FormFieldButton::setState called on a readOnly field\n");
     return gFalse;
   }
-  
-  if(btype == formButtonRadio) {
+
+  // A check button could behave as a radio button
+  // when it's in a set of more than 1 buttons
+  if (btype == formButtonRadio || btype == formButtonCheck) {
     if (!s && noAllOff)
       return gFalse; //don't allow to set all radio to off
 
@@ -842,17 +873,17 @@
       if (active_child >= 0) {
         FormWidgetButton* actChild = static_cast<FormWidgetButton*>(widgets[active_child]);
         if (actChild->getOnStr()) {
-          Object *obj1 = new Object();
-          obj1->initName(actChild->getOnStr());
-          obj.getDict()->set("V", obj1);
+          Object obj1;
+          obj1.initName(actChild->getOnStr());
+          obj.getDict()->set("V", &obj1);
           xref->setModifiedObject(&obj, ref);
         }
       }
     } else {
       active_child = -1;
-      Object *obj1 = new Object();
-      obj1->initName("Off");
-      obj.getDict()->set("V", obj1);
+      Object obj1;
+      obj1.initName("Off");
+      obj.getDict()->set("V", &obj1);
       xref->setModifiedObject(&obj, ref);
     }
   }
@@ -874,8 +905,9 @@
   Object obj1;
   content = NULL;
   multiline = password = fileSelect = doNotSpellCheck = doNotScroll = comb = richText = false;
+  maxLen = 0;
 
-  if (dict->lookup("Ff", &obj1)->isInt()) {
+  if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
     int flags = obj1.getInt();
     if (flags & 0x1000) // 13 -> Multiline
       multiline = true;
@@ -893,6 +925,11 @@
       richText = true;
   }
   obj1.free();
+
+  if (Form::fieldLookup(dict, "MaxLen", &obj1)->isInt()) {
+    maxLen = obj1.getInt();
+  }
+  obj1.free();
 }
 
 GooString* FormFieldText::getContentCopy ()
@@ -911,7 +948,7 @@
 
 FormFieldText::~FormFieldText()
 {
-
+  delete content;
 }
 
 
@@ -930,7 +967,7 @@
 
   combo = edit = multiselect = doNotSpellCheck = doCommitOnSelChange = false;
 
-  if (dict->lookup("Ff", &obj1)->isInt()) {
+  if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
     int flags = obj1.getInt();
     if (flags & 0x20000) // 18 -> Combo
       combo = true; 
@@ -954,6 +991,7 @@
     delete choices[i].optionName;
   }
   delete [] choices;
+  delete editedChoice;
 }
 
 void FormFieldChoice::deselectAll ()
@@ -1027,9 +1065,11 @@
 
 Form::Form(XRef *xrefA, Object* acroForm)
 {
+  Array *array = NULL;
   Object obj1;
   xref = xrefA;
-  Array *array = acroForm->dictLookup("Fields",&obj1)->getArray();
+  acroForm->dictLookup("Fields",&obj1);
+  if (obj1.isArray()) array = obj1.getArray();
   obj1.free();
   if(!array) {
     error(-1, "Can't get Fields array\n");
@@ -1037,43 +1077,64 @@
   size = 0;
   numFields = 0;
   rootFields = NULL;
-  for(int i=0; i<array->getLength(); i++) {
-    Object oref;
-    array->get(i, &obj1);
-    array->getNF(i, &oref);
-    if (!oref.isRef()) {
-      error(-1, "Direct object in rootFields");
-      continue;
-    }
-
-    if (numFields >= size) {
-      size += 16;
-      rootFields = (FormField**)greallocn(rootFields,size,sizeof(FormField*));
-    }
-
-    createFieldFromDict (&obj1, &rootFields[numFields++], xrefA, oref.getRef());
-
-    //Mark readonly field
-    Object obj3;
-    if (obj1.dictLookup("Ff", &obj3)->isInt()) {
-      int flags = obj3.getInt();
-      if (flags & 0x1)
-        rootFields[numFields-1]->setReadOnly(true);
-    }
-    obj3.free();
+  if (array) {
+    for(int i=0; i<array->getLength(); i++) {
+      Object oref;
+      array->get(i, &obj1);
+      array->getNF(i, &oref);
+      if (!oref.isRef()) {
+        error(-1, "Direct object in rootFields");
+        continue;
+      }
 
-    obj1.free();
-    oref.free();
+      if (numFields >= size) {
+        size += 16;
+        rootFields = (FormField**)greallocn(rootFields,size,sizeof(FormField*));
+      }
+
+      createFieldFromDict (&obj1, &rootFields[numFields++], xrefA, oref.getRef());
+
+      //Mark readonly field
+      Object obj3;
+      if (Form::fieldLookup(obj1.getDict (), "Ff", &obj3)->isInt()) {
+        int flags = obj3.getInt();
+        if (flags & 0x1)
+          rootFields[numFields-1]->setReadOnly(true);
+      }
+      obj3.free();
+
+      obj1.free();
+      oref.free();
+    }
   }
 
-  checkForNeedAppearances(acroForm); 
+  checkForNeedAppearances(acroForm);
 }
 
 Form::~Form() {
   int i;
   for(i = 0; i< numFields; ++i)
           delete rootFields[i];
-  delete [] rootFields;
+  gfree (rootFields);
+}
+
+// Look up an inheritable field dictionary entry.
+Object *Form::fieldLookup(Dict *field, char *key, Object *obj) {
+  Dict *dict;
+  Object parent;
+
+  dict = field;
+  if (!dict->lookup(key, obj)->isNull()) {
+    return obj;
+  }
+  obj->free();
+  if (dict->lookup("Parent", &parent)->isDict()) {
+    fieldLookup(parent.getDict(), key, obj);
+  } else {
+    obj->initNull();
+  }
+  parent.free();
+  return obj;
 }
 
 void Form::checkForNeedAppearances (Object *acroForm)
@@ -1097,7 +1158,8 @@
 void Form::createFieldFromDict (Object* obj, FormField** ptr, XRef *xrefA, const Ref& pref)
 {
     Object obj2;
-    if(obj->dictLookup("FT", &obj2)->isName("Btn")) {
+
+    if (Form::fieldLookup(obj->getDict (), "FT", &obj2)->isName("Btn")) {
       (*ptr) = new FormFieldButton(xrefA, obj, pref, this);
     } else if (obj2.isName("Tx")) {
       (*ptr) = new FormFieldText(xrefA, obj, pref, this);
@@ -1178,5 +1240,5 @@
 
 FormPageWidgets::~FormPageWidgets()
 {
-  // TODO free widgets ?
+  gfree (widgets);
 }
--- poppler/Stream.cc.orig
+++ poppler/Stream.cc
@@ -429,6 +429,13 @@ StreamPredictor::StreamPredictor(Stream 
   if (rowBytes < 0) {
     return;
   }
+  if (width <= 0 || nComps <= 0 || nBits <= 0 ||
+      nComps > gfxColorMaxComps ||
+      nBits > 16 ||
+      width >= INT_MAX / nComps ||      // check for overflow in nVals 
+      nVals >= (INT_MAX - 7) / nBits) { // check for overflow in rowBytes
+    return;
+  }
   predLine = (Guchar *)gmalloc(rowBytes);
   memset(predLine, 0, rowBytes);
   predIdx = rowBytes;
--- poppler/Form.h.orig	2007-04-14 15:16:59.000000000 -0400
+++ poppler/Form.h	2007-07-31 09:14:06.000000000 -0400
@@ -123,10 +123,12 @@
   FormWidgetButton(XRef *xrefA, Object *dict, unsigned num, Ref ref, FormFieldButton *p);
   ~FormWidgetButton ();
 
+  FormButtonType getButtonType() const;
+  
   void setState (GBool state, GBool calledByParent=gFalse);
   GBool getState ();
 
-  char* getOnStr () { return onStr; }
+  char* getOnStr () { return onStr->getCString(); }
 
   void loadDefaults();
 
@@ -143,7 +145,7 @@
   unsigned* siblingsID; // IDs of dependent buttons (each button of a radio field has all the others buttons
                         // of the same field in this array)
   int numSiblingsID;
-  char *onStr;
+  GooString *onStr;
   FormFieldButton *parent;
   GBool state;
 };
@@ -173,6 +175,7 @@
   bool isComb () const; 
   bool isRichText () const;
   bool isReadOnly () const;
+  int getMaxLen () const;
 protected:
   FormFieldText *parent;
 };
@@ -329,6 +332,8 @@
   bool noScroll () const { return doNotScroll; }
   bool isComb () const { return comb; }
   bool isRichText () const { return richText; }
+
+  int getMaxLen () const { return maxLen; }
 protected:
   GooString* content;
   bool multiline;
@@ -338,6 +343,7 @@
   bool doNotScroll;
   bool comb;
   bool richText;
+  int maxLen;
 };
 
 //------------------------------------------------------------------------
@@ -426,6 +432,8 @@
 
   ~Form();
 
+  static Object *fieldLookup(Dict *field, char *key, Object *obj);
+  
   int getNumFields() const { return numFields; }
   FormField* getRootField(int i) const { return rootFields[i]; }
 
