Switch CFX_SAXReader to use std::stack.

Fix some nullptr errors.

BUG=pdfium:608

Review-Url: https://codereview.chromium.org/2378133003
diff --git a/xfa/fde/xml/cfx_saxreader.cpp b/xfa/fde/xml/cfx_saxreader.cpp
index 2fde9d9..bd76e79 100644
--- a/xfa/fde/xml/cfx_saxreader.cpp
+++ b/xfa/fde/xml/cfx_saxreader.cpp
@@ -7,6 +7,7 @@
 #include "xfa/fde/xml/cfx_saxreader.h"
 
 #include <algorithm>
+#include <utility>
 
 #include "xfa/fxfa/xfa_checksum.h"
 
@@ -94,6 +95,7 @@
   m_dwBufIndex = 0;
   return TRUE;
 }
+
 FX_BOOL CFX_SAXFile::ReadNextBlock() {
   ASSERT(m_pFile);
   uint32_t dwSize = m_dwEnd - m_dwCur;
@@ -107,6 +109,7 @@
   m_dwBufIndex = 0;
   return TRUE;
 }
+
 void CFX_SAXFile::Reset() {
   if (m_pBuf) {
     FX_Free(m_pBuf);
@@ -114,12 +117,11 @@
   }
   m_pFile = nullptr;
 }
+
 CFX_SAXReader::CFX_SAXReader()
     : m_File(),
       m_pHandler(nullptr),
       m_iState(-1),
-      m_pRoot(nullptr),
-      m_pCurItem(nullptr),
       m_dwItemID(0),
       m_iDataSize(256),
       m_iNameSize(256),
@@ -139,16 +141,12 @@
     m_pszName = nullptr;
   }
 }
+
 void CFX_SAXReader::Reset() {
   m_File.Reset();
-  CFX_SAXItem* pItem = m_pRoot;
-  while (pItem) {
-    CFX_SAXItem* pNext = pItem->m_pNext;
-    delete pItem;
-    pItem = pNext;
-  }
-  m_pRoot = nullptr;
-  m_pCurItem = nullptr;
+  while (!m_Stack.empty())
+    m_Stack.pop();
+
   m_dwItemID = 0;
   m_SkipStack.RemoveAll();
   m_SkipChar = 0;
@@ -156,36 +154,36 @@
   m_iEntityStart = -1;
   m_iNameLength = 0;
   m_iDataPos = 0;
-  if (m_pCommentContext) {
-    delete m_pCommentContext;
-    m_pCommentContext = nullptr;
-  }
+  delete m_pCommentContext;
+  m_pCommentContext = nullptr;
 }
-inline void CFX_SAXReader::Push() {
-  CFX_SAXItem* pNew = new CFX_SAXItem;
-  pNew->m_dwID = ++m_dwItemID;
-  pNew->m_bSkip = m_pCurItem->m_bSkip;
-  pNew->m_pPrev = m_pCurItem;
-  m_pCurItem->m_pNext = pNew;
-  m_pCurItem = pNew;
+
+void CFX_SAXReader::Push() {
+  std::unique_ptr<CFX_SAXItem> pNew(WrapUnique(new CFX_SAXItem(++m_dwItemID)));
+  if (!m_Stack.empty())
+    pNew->m_bSkip = m_Stack.top()->m_bSkip;
+  m_Stack.push(std::move(pNew));
 }
-inline void CFX_SAXReader::Pop() {
-  if (!m_pCurItem) {
-    return;
-  }
-  CFX_SAXItem* pPrev = m_pCurItem->m_pPrev;
-  pPrev->m_pNext = nullptr;
-  delete m_pCurItem;
-  m_pCurItem = pPrev;
+
+void CFX_SAXReader::Pop() {
+  if (!m_Stack.empty())
+    m_Stack.pop();
 }
-inline void CFX_SAXReader::AppendData(uint8_t ch) {
+
+CFX_SAXItem* CFX_SAXReader::GetCurrentItem() const {
+  return m_Stack.empty() ? nullptr : m_Stack.top().get();
+}
+
+void CFX_SAXReader::AppendData(uint8_t ch) {
   ReallocDataBuffer();
   m_pszData[m_iDataPos++] = ch;
 }
-inline void CFX_SAXReader::AppendName(uint8_t ch) {
+
+void CFX_SAXReader::AppendName(uint8_t ch) {
   ReallocNameBuffer();
   m_pszName[m_iDataPos++] = ch;
 }
+
 void CFX_SAXReader::ReallocDataBuffer() {
   if (m_iDataPos < m_iDataSize) {
     return;
@@ -197,6 +195,7 @@
   }
   m_pszData = (uint8_t*)FX_Realloc(uint8_t, m_pszData, m_iDataSize);
 }
+
 void CFX_SAXReader::ReallocNameBuffer() {
   if (m_iDataPos < m_iNameSize) {
     return;
@@ -208,9 +207,11 @@
   }
   m_pszName = (uint8_t*)FX_Realloc(uint8_t, m_pszName, m_iNameSize);
 }
-inline FX_BOOL CFX_SAXReader::SkipSpace(uint8_t ch) {
+
+FX_BOOL CFX_SAXReader::SkipSpace(uint8_t ch) {
   return (m_dwParseMode & CFX_SaxParseMode_NotSkipSpace) == 0 && ch < 0x21;
 }
+
 int32_t CFX_SAXReader::StartParse(IFX_FileRead* pFile,
                                   uint32_t dwStart,
                                   uint32_t dwLen,
@@ -225,9 +226,8 @@
   m_ePrevMode = CFX_SaxMode::Text;
   m_bCharData = FALSE;
   m_dwDataOffset = 0;
-  m_pRoot = m_pCurItem = new CFX_SAXItem;
-  m_pCurItem->m_dwID = ++m_dwItemID;
   m_dwParseMode = dwParseMode;
+  m_Stack.emplace(new CFX_SAXItem(++m_dwItemID));
   return 0;
 }
 
@@ -338,6 +338,7 @@
     m_iDataPos++;
   }
 }
+
 void CFX_SAXReader::ParseText() {
   if (m_CurByte == '<') {
     if (m_iDataPos > 0) {
@@ -357,9 +358,10 @@
   }
   ParseChar(m_CurByte);
 }
+
 void CFX_SAXReader::ParseNodeStart() {
   if (m_CurByte == '?') {
-    m_pCurItem->m_eNode = CFX_SAXItem::Type::Instruction;
+    GetCurrentItem()->m_eNode = CFX_SAXItem::Type::Instruction;
     m_eMode = CFX_SaxMode::TagName;
     return;
   }
@@ -378,15 +380,16 @@
   }
   if (m_CurByte > 0x20) {
     m_dwDataOffset = m_File.m_dwBufIndex;
-    m_pCurItem->m_eNode = CFX_SAXItem::Type::Tag;
+    GetCurrentItem()->m_eNode = CFX_SAXItem::Type::Tag;
     m_eMode = CFX_SaxMode::TagName;
     AppendData(m_CurByte);
   }
 }
+
 void CFX_SAXReader::ParseDeclOrComment() {
   if (m_CurByte == '-') {
     m_eMode = CFX_SaxMode::Comment;
-    m_pCurItem->m_eNode = CFX_SAXItem::Type::Comment;
+    GetCurrentItem()->m_eNode = CFX_SAXItem::Type::Comment;
     if (!m_pCommentContext)
       m_pCommentContext = new CFX_SAXCommentContext;
 
@@ -479,18 +482,21 @@
   }
   AppendName(m_CurByte);
 }
+
 void CFX_SAXReader::ParseTagAttributeEqual() {
   if (m_CurByte == '=') {
     m_SkipChar = 0;
     m_eMode = CFX_SaxMode::TagAttributeValue;
     return;
-  } else if (m_pCurItem->m_eNode == CFX_SAXItem::Type::Instruction) {
+  }
+  if (GetCurrentItem()->m_eNode == CFX_SAXItem::Type::Instruction) {
     m_iDataPos = m_iNameLength;
     AppendName(0x20);
     m_eMode = CFX_SaxMode::TargetData;
     ParseTargetData();
   }
 }
+
 void CFX_SAXReader::ParseTagAttributeValue() {
   if (m_SkipChar) {
     if (m_SkipChar == m_CurByte) {
@@ -517,9 +523,10 @@
     }
   }
 }
+
 void CFX_SAXReader::ParseMaybeClose() {
   if (m_CurByte == '>') {
-    if (m_pCurItem->m_eNode == CFX_SAXItem::Type::Instruction) {
+    if (GetCurrentItem()->m_eNode == CFX_SAXItem::Type::Instruction) {
       m_iNameLength = m_iDataPos;
       m_iDataPos = 0;
       if (m_pHandler) {
@@ -647,69 +654,79 @@
 }
 
 void CFX_SAXReader::NotifyData() {
-  if (m_pCurItem->m_eNode == CFX_SAXItem::Type::Tag)
+  CFX_SAXItem* pItem = GetCurrentItem();
+  if (!pItem)
+    return;
+
+  if (pItem->m_eNode == CFX_SAXItem::Type::Tag)
     m_pHandler->OnTagData(
-        m_pCurItem->m_pNode,
+        pItem->m_pNode,
         m_bCharData ? CFX_SAXItem::Type::CharData : CFX_SAXItem::Type::Text,
         CFX_ByteStringC(m_pszData, m_iDataLength),
         m_File.m_dwCur + m_dwDataOffset);
 }
 
 void CFX_SAXReader::NotifyEnter() {
-  if (m_pCurItem->m_eNode == CFX_SAXItem::Type::Tag ||
-      m_pCurItem->m_eNode == CFX_SAXItem::Type::Instruction) {
-    m_pCurItem->m_pNode =
-        m_pHandler->OnTagEnter(CFX_ByteStringC(m_pszData, m_iDataLength),
-                               m_pCurItem->m_eNode, m_dwNodePos);
+  CFX_SAXItem* pItem = GetCurrentItem();
+  if (pItem->m_eNode == CFX_SAXItem::Type::Tag ||
+      pItem->m_eNode == CFX_SAXItem::Type::Instruction) {
+    pItem->m_pNode = m_pHandler->OnTagEnter(
+        CFX_ByteStringC(m_pszData, m_iDataLength), pItem->m_eNode, m_dwNodePos);
   }
 }
 
 void CFX_SAXReader::NotifyAttribute() {
-  if (m_pCurItem->m_eNode == CFX_SAXItem::Type::Tag ||
-      m_pCurItem->m_eNode == CFX_SAXItem::Type::Instruction) {
-    m_pHandler->OnTagAttribute(m_pCurItem->m_pNode,
+  CFX_SAXItem* pItem = GetCurrentItem();
+  if (pItem->m_eNode == CFX_SAXItem::Type::Tag ||
+      pItem->m_eNode == CFX_SAXItem::Type::Instruction) {
+    m_pHandler->OnTagAttribute(pItem->m_pNode,
                                CFX_ByteStringC(m_pszName, m_iNameLength),
                                CFX_ByteStringC(m_pszData, m_iDataLength));
   }
 }
 
 void CFX_SAXReader::NotifyBreak() {
-  if (m_pCurItem->m_eNode == CFX_SAXItem::Type::Tag)
-    m_pHandler->OnTagBreak(m_pCurItem->m_pNode);
+  CFX_SAXItem* pItem = GetCurrentItem();
+  if (pItem->m_eNode == CFX_SAXItem::Type::Tag)
+    m_pHandler->OnTagBreak(pItem->m_pNode);
 }
 
 void CFX_SAXReader::NotifyClose() {
-  if (m_pCurItem->m_eNode == CFX_SAXItem::Type::Tag ||
-      m_pCurItem->m_eNode == CFX_SAXItem::Type::Instruction) {
-    m_pHandler->OnTagClose(m_pCurItem->m_pNode, m_dwNodePos);
+  CFX_SAXItem* pItem = GetCurrentItem();
+  if (pItem->m_eNode == CFX_SAXItem::Type::Tag ||
+      pItem->m_eNode == CFX_SAXItem::Type::Instruction) {
+    m_pHandler->OnTagClose(pItem->m_pNode, m_dwNodePos);
   }
 }
 
 void CFX_SAXReader::NotifyEnd() {
-  if (m_pCurItem->m_eNode != CFX_SAXItem::Type::Tag)
+  CFX_SAXItem* pItem = GetCurrentItem();
+  if (!pItem || pItem->m_eNode != CFX_SAXItem::Type::Tag)
     return;
 
-  m_pHandler->OnTagEnd(m_pCurItem->m_pNode,
+  m_pHandler->OnTagEnd(pItem->m_pNode,
                        CFX_ByteStringC(m_pszData, m_iDataLength), m_dwNodePos);
 }
 
 void CFX_SAXReader::NotifyTargetData() {
-  if (m_pCurItem->m_eNode == CFX_SAXItem::Type::Instruction) {
-    m_pHandler->OnTargetData(m_pCurItem->m_pNode, m_pCurItem->m_eNode,
+  CFX_SAXItem* pItem = GetCurrentItem();
+  if (pItem->m_eNode == CFX_SAXItem::Type::Instruction) {
+    m_pHandler->OnTargetData(pItem->m_pNode, pItem->m_eNode,
                              CFX_ByteStringC(m_pszName, m_iNameLength),
                              m_dwNodePos);
-  } else if (m_pCurItem->m_eNode == CFX_SAXItem::Type::Comment) {
-    m_pHandler->OnTargetData(m_pCurItem->m_pNode, m_pCurItem->m_eNode,
+  } else if (pItem->m_eNode == CFX_SAXItem::Type::Comment) {
+    m_pHandler->OnTargetData(pItem->m_pNode, pItem->m_eNode,
                              CFX_ByteStringC(m_pszData, m_iDataLength),
                              m_dwNodePos);
   }
 }
 
 void CFX_SAXReader::SkipCurrentNode() {
-  if (!m_pCurItem)
+  CFX_SAXItem* pItem = GetCurrentItem();
+  if (!pItem)
     return;
 
-  m_pCurItem->m_bSkip = TRUE;
+  pItem->m_bSkip = TRUE;
 }
 
 void CFX_SAXReader::SetHandler(CXFA_SAXReaderHandler* pHandler) {
diff --git a/xfa/fde/xml/cfx_saxreader.h b/xfa/fde/xml/cfx_saxreader.h
index 7253c8d..b6bedfe 100644
--- a/xfa/fde/xml/cfx_saxreader.h
+++ b/xfa/fde/xml/cfx_saxreader.h
@@ -7,6 +7,9 @@
 #ifndef XFA_FDE_XML_CFX_SAXREADER_H_
 #define XFA_FDE_XML_CFX_SAXREADER_H_
 
+#include <memory>
+#include <stack>
+
 #include "core/fxcrt/fx_basic.h"
 
 class CXFA_SAXContext;
@@ -23,20 +26,13 @@
     CharData,
   };
 
-  CFX_SAXItem()
-      : m_pNode(nullptr),
-        m_eNode(Type::Unknown),
-        m_dwID(0),
-        m_bSkip(FALSE),
-        m_pPrev(nullptr),
-        m_pNext(nullptr) {}
+  explicit CFX_SAXItem(uint32_t id)
+      : m_pNode(nullptr), m_eNode(Type::Unknown), m_dwID(id), m_bSkip(FALSE) {}
 
   CXFA_SAXContext* m_pNode;
   Type m_eNode;
-  uint32_t m_dwID;
+  const uint32_t m_dwID;
   FX_BOOL m_bSkip;
-  CFX_SAXItem* m_pPrev;
-  CFX_SAXItem* m_pNext;
 };
 
 class CFX_SAXFile {
@@ -103,6 +99,7 @@
   void Reset();
   void Push();
   void Pop();
+  CFX_SAXItem* GetCurrentItem() const;
   FX_BOOL SkipSpace(uint8_t ch);
   void SkipNode();
   void NotifyData();
@@ -119,8 +116,7 @@
   CFX_SAXFile m_File;
   CXFA_SAXReaderHandler* m_pHandler;
   int32_t m_iState;
-  CFX_SAXItem* m_pRoot;
-  CFX_SAXItem* m_pCurItem;
+  std::stack<std::unique_ptr<CFX_SAXItem>> m_Stack;
   uint32_t m_dwItemID;
   CFX_SaxMode m_eMode;
   CFX_SaxMode m_ePrevMode;