A crasher due to lacking 'template' node in XFA file

A template node is mandatory in XFA file. Pdfium should
ignore processing it when no template node is found in
XFA file.

BUG=pdfium:216
R=tsepez@chromium.org

Review URL: https://codereview.chromium.org/1423903002 .
diff --git a/BUILD.gn b/BUILD.gn
index fcba1f1..1ab969a 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1512,6 +1512,7 @@
     "testing/embedder_test.h",
     "testing/embedder_test_mock_delegate.h",
     "testing/embedder_test_timer_handling_delegate.h",
+    "xfa/src/fxfa/src/parser/xfa_parser_imp_embeddertest.cpp",
   ]
   deps = [
     "//testing/gmock",
diff --git a/pdfium.gyp b/pdfium.gyp
index 3d35cab..991dac4 100644
--- a/pdfium.gyp
+++ b/pdfium.gyp
@@ -807,6 +807,7 @@
         'testing/embedder_test.h',
         'testing/embedder_test_mock_delegate.h',
         'testing/embedder_test_timer_handling_delegate.h',
+        'xfa/src/fxfa/src/parser/xfa_parser_imp_embeddertest.cpp',
       ],
       'conditions': [
         ['pdf_enable_v8==1', {
diff --git a/testing/resources/bug_216.in b/testing/resources/bug_216.in
new file mode 100644
index 0000000..1ecd862
--- /dev/null
+++ b/testing/resources/bug_216.in
@@ -0,0 +1,39 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+  /AcroForm 4 0 R
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Pages
+  /Count 1
+>>
+endobj
+{{object 4 0}} <<
+  /XFA [
+    (xdp:xdp) 23 0 R
+    (form) 29 0 R
+    (</xdp:xdp>) 30 0 R]
+>>
+endobj
+{{object 23 0}} <<
+>>stream
+<?xml version="1.0" encoding="UTF-8"?>
+<xdp:xdp xmlns:xdp="http://www.foxitsoftware.com/">
+endstream
+endobj
+{{object 29 0}} <<
+>>stream
+<form xmlns="http://www.xfa.org/schema/xfa-form/2.6/">
+</form>
+endstream
+endobj
+{{object 30 0}} <<
+>>stream
+</xdp:xdp>
+endstream
+endobj
+trailer
+<</Root 1 0 R>>
+%%EOF
diff --git a/testing/resources/bug_216.pdf b/testing/resources/bug_216.pdf
new file mode 100644
index 0000000..2d59872
--- /dev/null
+++ b/testing/resources/bug_216.pdf
@@ -0,0 +1,40 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+  /AcroForm 4 0 R
+>>
+endobj
+2 0 obj <<
+  /Type /Pages
+  /Count 1
+>>
+endobj
+4 0 obj <<
+  /XFA [
+    (xdp:xdp) 23 0 R
+    (form) 29 0 R
+    (</xdp:xdp>) 30 0 R]
+>>
+endobj
+23 0 obj <<
+>>stream
+<?xml version="1.0" encoding="UTF-8"?>
+<xdp:xdp xmlns:xdp="http://www.foxitsoftware.com/">
+endstream
+endobj
+29 0 obj <<
+>>stream
+<form xmlns="http://www.xfa.org/schema/xfa-form/2.6/">
+</form>
+endstream
+endobj
+30 0 obj <<
+>>stream
+</xdp:xdp>
+endstream
+endobj
+trailer
+<</Root 1 0 R>>
+%%EOF
diff --git a/xfa/src/fxfa/src/parser/xfa_parser_imp.cpp b/xfa/src/fxfa/src/parser/xfa_parser_imp.cpp
index 9e85c1f..48547d7 100644
--- a/xfa/src/fxfa/src/parser/xfa_parser_imp.cpp
+++ b/xfa/src/fxfa/src/parser/xfa_parser_imp.cpp
@@ -386,12 +386,12 @@
           pXMLDocumentNode, XFA_GetPacketByIndex(XFA_PACKET_XDP)->pName,

           XFA_GetPacketByIndex(XFA_PACKET_XDP)->pURI,

           XFA_GetPacketByIndex(XFA_PACKET_XDP)->eFlags)) {

-    return NULL;

+    return nullptr;

   }

   CXFA_Node* pXFARootNode =

       m_pFactory->CreateNode(XFA_XDPPACKET_XDP, XFA_ELEMENT_Xfa);

   if (!pXFARootNode) {

-    return NULL;

+    return nullptr;

   }

   m_pRootNode = pXFARootNode;

   pXFARootNode->SetCData(XFA_ATTRIBUTE_Name, FX_WSTRC(L"xfa"));

@@ -408,8 +408,8 @@
       }

     }

   }

-  IFDE_XMLNode* pXMLConfigDOMRoot = NULL;

-  CXFA_Node* pXFAConfigDOMRoot = NULL;

+  IFDE_XMLNode* pXMLConfigDOMRoot = nullptr;

+  CXFA_Node* pXFAConfigDOMRoot = nullptr;

   {

     for (IFDE_XMLNode* pChildItem =

              pXMLDocumentNode->GetNodeItem(IFDE_XMLNode::FirstChild);

@@ -423,7 +423,7 @@
       }

       if (CXFA_Node* pChildNode =

               pXFARootNode->GetFirstChildByName(pPacketInfo->uHash)) {

-        return NULL;

+        return nullptr;

       }

       pXMLConfigDOMRoot = pChildItem;

       pXFAConfigDOMRoot =

@@ -431,8 +431,9 @@
       pXFARootNode->InsertChild(pXFAConfigDOMRoot, NULL);

     }

   }

-  IFDE_XMLNode* pXMLDatasetsDOMRoot = NULL;

-  IFDE_XMLNode* pXMLFormDOMRoot = NULL;

+  IFDE_XMLNode* pXMLDatasetsDOMRoot = nullptr;

+  IFDE_XMLNode* pXMLFormDOMRoot = nullptr;

+  IFDE_XMLNode* pXMLTemplateDOMRoot = nullptr;

   {

     for (IFDE_XMLNode* pChildItem =

              pXMLDocumentNode->GetNodeItem(IFDE_XMLNode::FirstChild);

@@ -453,7 +454,7 @@
         if (!XFA_FDEExtension_MatchNodeName(pElement, pPacketInfo->pName,

                                             pPacketInfo->pURI,

                                             pPacketInfo->eFlags)) {

-          pPacketInfo = NULL;

+          pPacketInfo = nullptr;

         }

       }

       XFA_XDPPACKET ePacket =

@@ -463,29 +464,41 @@
       }

       if (ePacket == XFA_XDPPACKET_Datasets) {

         if (pXMLDatasetsDOMRoot) {

-          pXMLDatasetsDOMRoot = NULL;

-          return NULL;

+          return nullptr;

         }

         pXMLDatasetsDOMRoot = pElement;

       } else if (ePacket == XFA_XDPPACKET_Form) {

         if (pXMLFormDOMRoot) {

-          pXMLFormDOMRoot = NULL;

-          return NULL;

+          return nullptr;

         }

         pXMLFormDOMRoot = pElement;

+      } else if (ePacket == XFA_XDPPACKET_Template) {

+        if (pXMLTemplateDOMRoot) {

+          // Found a duplicate template packet.

+          return nullptr;

+        }

+        CXFA_Node* pPacketNode = ParseAsXDPPacket(pElement, ePacket);

+        if (pPacketNode) {

+          pXMLTemplateDOMRoot = pElement;

+          pXFARootNode->InsertChild(pPacketNode);

+        }

       } else {

         CXFA_Node* pPacketNode = ParseAsXDPPacket(pElement, ePacket);

         if (pPacketNode) {

           if (pPacketInfo &&

               (pPacketInfo->eFlags & XFA_XDPPACKET_FLAGS_SUPPORTONE) &&

               pXFARootNode->GetFirstChildByName(pPacketInfo->uHash)) {

-            return NULL;

+            return nullptr;

           }

           pXFARootNode->InsertChild(pPacketNode);

         }

       }

     }

   }

+  if (!pXMLTemplateDOMRoot) {

+    // No template is found.

+    return nullptr;

+  }

   if (pXMLDatasetsDOMRoot) {

     CXFA_Node* pPacketNode =

         ParseAsXDPPacket(pXMLDatasetsDOMRoot, XFA_XDPPACKET_Datasets);

diff --git a/xfa/src/fxfa/src/parser/xfa_parser_imp_embeddertest.cpp b/xfa/src/fxfa/src/parser/xfa_parser_imp_embeddertest.cpp
new file mode 100644
index 0000000..5a3059c
--- /dev/null
+++ b/xfa/src/fxfa/src/parser/xfa_parser_imp_embeddertest.cpp
@@ -0,0 +1,15 @@
+// Copyright 2015 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "../../../../../testing/embedder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class XFAParserImpEmbeddertest : public EmbedderTest {};
+
+TEST_F(XFAParserImpEmbeddertest, Bug_216) {
+    EXPECT_TRUE(OpenDocument("testing/resources/bug_216.pdf"));
+    FPDF_PAGE page = LoadPage(0);
+    EXPECT_NE(nullptr, page);
+    UnloadPage(page);
+}
\ No newline at end of file