Limit recursion in CXML_Parser::ParseElement().

BUG=chromium:716526

Change-Id: Idbe4624ab2193cee2931c69ed023dd2c1679d124
Reviewed-on: https://pdfium-review.googlesource.com/4615
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcrt/xml/cxml_element.cpp b/core/fxcrt/xml/cxml_element.cpp
index 17caebf..95a6dba 100644
--- a/core/fxcrt/xml/cxml_element.cpp
+++ b/core/fxcrt/xml/cxml_element.cpp
@@ -9,6 +9,15 @@
 #include "core/fxcrt/xml/cxml_content.h"
 #include "core/fxcrt/xml/cxml_parser.h"
 
+// static
+std::unique_ptr<CXML_Element> CXML_Element::Parse(const void* pBuffer,
+                                                  size_t size) {
+  CXML_Parser parser;
+  if (!parser.Init(static_cast<const uint8_t*>(pBuffer), size))
+    return nullptr;
+  return parser.ParseElement(nullptr, false);
+}
+
 CXML_Element::CXML_Element(const CXML_Element* pParent,
                            const CFX_ByteStringC& qSpace,
                            const CFX_ByteStringC& tagname)
diff --git a/core/fxcrt/xml/cxml_parser.cpp b/core/fxcrt/xml/cxml_parser.cpp
index 691a86e..dc3978e 100644
--- a/core/fxcrt/xml/cxml_parser.cpp
+++ b/core/fxcrt/xml/cxml_parser.cpp
@@ -53,6 +53,8 @@
     0x1A, 0x1A, 0x01, 0x01,
 };
 
+constexpr int kMaxDepth = 1024;
+
 bool g_FXCRT_XML_IsWhiteSpace(uint8_t ch) {
   return !!(g_FXCRT_XML_ByteTypes[ch] & FXCRTM_XML_CHARTYPE_SpaceChar);
 }
@@ -369,6 +371,16 @@
 
 std::unique_ptr<CXML_Element> CXML_Parser::ParseElement(CXML_Element* pParent,
                                                         bool bStartTag) {
+  return ParseElementInternal(pParent, bStartTag, 0);
+}
+
+std::unique_ptr<CXML_Element> CXML_Parser::ParseElementInternal(
+    CXML_Element* pParent,
+    bool bStartTag,
+    int nDepth) {
+  if (nDepth > kMaxDepth)
+    return nullptr;
+
   m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
   if (IsEOF())
     return nullptr;
@@ -476,8 +488,8 @@
             bCDATA = false;
             iState = 0;
             m_dwIndex--;
-            std::unique_ptr<CXML_Element> pSubElement(
-                ParseElement(pElement.get(), true));
+            std::unique_ptr<CXML_Element> pSubElement =
+                ParseElementInternal(pElement.get(), true, nDepth + 1);
             if (!pSubElement)
               break;
 
@@ -529,11 +541,3 @@
   pContent->Set(bCDATA, content);
   pElement->m_Children.push_back({CXML_Element::Content, pContent});
 }
-
-std::unique_ptr<CXML_Element> CXML_Element::Parse(const void* pBuffer,
-                                                  size_t size) {
-  CXML_Parser parser;
-  if (!parser.Init(static_cast<const uint8_t*>(pBuffer), size))
-    return nullptr;
-  return parser.ParseElement(nullptr, false);
-}
diff --git a/core/fxcrt/xml/cxml_parser.h b/core/fxcrt/xml/cxml_parser.h
index 371edf2..33bd711 100644
--- a/core/fxcrt/xml/cxml_parser.h
+++ b/core/fxcrt/xml/cxml_parser.h
@@ -42,6 +42,10 @@
   void InsertCDATASegment(CFX_UTF8Decoder& decoder, CXML_Element* pElement);
 
  private:
+  std::unique_ptr<CXML_Element> ParseElementInternal(CXML_Element* pParent,
+                                                     bool bStartTag,
+                                                     int nDepth);
+
   std::unique_ptr<CXML_DataBufAcc> m_pDataAcc;
   FX_FILESIZE m_nOffset;
   const uint8_t* m_pBuffer;