Fix potential UAF in ConcatInPlace.
[pdfium.git] / core / src / fxcrt / fx_basic_list.cpp
index 92b3d2c..c9619f9 100644 (file)
-// Copyright 2014 PDFium Authors. All rights reserved.\r
-// Use of this source code is governed by a BSD-style license that can be\r
-// found in the LICENSE file.\r
\r
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
-\r
-#include "../../include/fxcrt/fx_basic.h"\r
-#include "plex.h"\r
-CFX_PtrList::CFX_PtrList(int nBlockSize, IFX_Allocator* pAllocator)\r
-    : m_pAllocator(pAllocator)\r
-    , m_pNodeHead(NULL)\r
-    , m_pNodeTail(NULL)\r
-    , m_nCount(0)\r
-    , m_pNodeFree(NULL)\r
-    , m_pBlocks(NULL)\r
-    , m_nBlockSize(nBlockSize)\r
-{\r
-}\r
-FX_POSITION CFX_PtrList::AddTail(void* newElement)\r
-{\r
-    CNode* pNewNode = NewNode(m_pNodeTail, NULL);\r
-    pNewNode->data = newElement;\r
-    if (m_pNodeTail != NULL) {\r
-        m_pNodeTail->pNext = pNewNode;\r
-    } else {\r
-        m_pNodeHead = pNewNode;\r
-    }\r
-    m_pNodeTail = pNewNode;\r
-    return (FX_POSITION) pNewNode;\r
-}\r
-FX_POSITION CFX_PtrList::AddHead(void* newElement)\r
-{\r
-    CNode* pNewNode = NewNode(NULL, m_pNodeHead);\r
-    pNewNode->data = newElement;\r
-    if (m_pNodeHead != NULL) {\r
-        m_pNodeHead->pPrev = pNewNode;\r
-    } else {\r
-        m_pNodeTail = pNewNode;\r
-    }\r
-    m_pNodeHead = pNewNode;\r
-    return (FX_POSITION) pNewNode;\r
-}\r
-FX_POSITION CFX_PtrList::InsertAfter(FX_POSITION position, void* newElement)\r
-{\r
-    if (position == NULL) {\r
-        return AddTail(newElement);\r
-    }\r
-    CNode* pOldNode = (CNode*) position;\r
-    CNode* pNewNode = NewNode(pOldNode, pOldNode->pNext);\r
-    pNewNode->data = newElement;\r
-    if (pOldNode->pNext != NULL) {\r
-        pOldNode->pNext->pPrev = pNewNode;\r
-    } else {\r
-        m_pNodeTail = pNewNode;\r
-    }\r
-    pOldNode->pNext = pNewNode;\r
-    return (FX_POSITION) pNewNode;\r
-}\r
-void CFX_PtrList::RemoveAt(FX_POSITION position)\r
-{\r
-    CNode* pOldNode = (CNode*) position;\r
-    if (pOldNode == m_pNodeHead) {\r
-        m_pNodeHead = pOldNode->pNext;\r
-    } else {\r
-        pOldNode->pPrev->pNext = pOldNode->pNext;\r
-    }\r
-    if (pOldNode == m_pNodeTail) {\r
-        m_pNodeTail = pOldNode->pPrev;\r
-    } else {\r
-        pOldNode->pNext->pPrev = pOldNode->pPrev;\r
-    }\r
-    FreeNode(pOldNode);\r
-}\r
-void CFX_PtrList::FreeNode(CFX_PtrList::CNode* pNode)\r
-{\r
-    pNode->pNext = m_pNodeFree;\r
-    m_pNodeFree = pNode;\r
-    m_nCount--;\r
-    if (m_nCount == 0) {\r
-        RemoveAll();\r
-    }\r
-}\r
-void CFX_PtrList::RemoveAll()\r
-{\r
-    m_nCount = 0;\r
-    m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;\r
-    m_pBlocks->FreeDataChain(m_pAllocator);\r
-    m_pBlocks = NULL;\r
-}\r
-CFX_PtrList::CNode*\r
-CFX_PtrList::NewNode(CFX_PtrList::CNode* pPrev, CFX_PtrList::CNode* pNext)\r
-{\r
-    if (m_pNodeFree == NULL) {\r
-        CFX_Plex* pNewBlock = CFX_Plex::Create(m_pAllocator, m_pBlocks, m_nBlockSize, sizeof(CNode));\r
-        CNode* pNode = (CNode*)pNewBlock->data();\r
-        pNode += m_nBlockSize - 1;\r
-        for (int i = m_nBlockSize - 1; i >= 0; i--, pNode--) {\r
-            pNode->pNext = m_pNodeFree;\r
-            m_pNodeFree = pNode;\r
-        }\r
-    }\r
-    ASSERT(m_pNodeFree != NULL);\r
-    CFX_PtrList::CNode* pNode = m_pNodeFree;\r
-    m_pNodeFree = m_pNodeFree->pNext;\r
-    pNode->pPrev = pPrev;\r
-    pNode->pNext = pNext;\r
-    m_nCount++;\r
-    ASSERT(m_nCount > 0);\r
-    pNode->data = 0;\r
-    return pNode;\r
-}\r
-CFX_PtrList::~CFX_PtrList()\r
-{\r
-    RemoveAll();\r
-    ASSERT(m_nCount == 0);\r
-}\r
-FX_POSITION CFX_PtrList::FindIndex(int nIndex) const\r
-{\r
-    if (nIndex >= m_nCount || nIndex < 0) {\r
-        return NULL;\r
-    }\r
-    CNode* pNode = m_pNodeHead;\r
-    while (nIndex--) {\r
-        pNode = pNode->pNext;\r
-    }\r
-    return (FX_POSITION) pNode;\r
-}\r
-FX_POSITION CFX_PtrList::Find(void* searchValue, FX_POSITION startAfter) const\r
-{\r
-    CNode* pNode = (CNode*) startAfter;\r
-    if (pNode == NULL) {\r
-        pNode = m_pNodeHead;\r
-    } else {\r
-        pNode = pNode->pNext;\r
-    }\r
-    for (; pNode != NULL; pNode = pNode->pNext)\r
-        if (pNode->data == searchValue) {\r
-            return (FX_POSITION) pNode;\r
-        }\r
-    return NULL;\r
-}\r
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fxcrt/fx_basic.h"
+#include "plex.h"
+CFX_PtrList::CFX_PtrList(int nBlockSize)
+    : m_pNodeHead(NULL)
+    , m_pNodeTail(NULL)
+    , m_nCount(0)
+    , m_pNodeFree(NULL)
+    , m_pBlocks(NULL)
+    , m_nBlockSize(nBlockSize)
+{
+}
+FX_POSITION CFX_PtrList::AddTail(void* newElement)
+{
+    CNode* pNewNode = NewNode(m_pNodeTail, NULL);
+    pNewNode->data = newElement;
+    if (m_pNodeTail != NULL) {
+        m_pNodeTail->pNext = pNewNode;
+    } else {
+        m_pNodeHead = pNewNode;
+    }
+    m_pNodeTail = pNewNode;
+    return (FX_POSITION) pNewNode;
+}
+FX_POSITION CFX_PtrList::AddHead(void* newElement)
+{
+    CNode* pNewNode = NewNode(NULL, m_pNodeHead);
+    pNewNode->data = newElement;
+    if (m_pNodeHead != NULL) {
+        m_pNodeHead->pPrev = pNewNode;
+    } else {
+        m_pNodeTail = pNewNode;
+    }
+    m_pNodeHead = pNewNode;
+    return (FX_POSITION) pNewNode;
+}
+FX_POSITION CFX_PtrList::InsertAfter(FX_POSITION position, void* newElement)
+{
+    if (position == NULL) {
+        return AddTail(newElement);
+    }
+    CNode* pOldNode = (CNode*) position;
+    CNode* pNewNode = NewNode(pOldNode, pOldNode->pNext);
+    pNewNode->data = newElement;
+    if (pOldNode->pNext != NULL) {
+        pOldNode->pNext->pPrev = pNewNode;
+    } else {
+        m_pNodeTail = pNewNode;
+    }
+    pOldNode->pNext = pNewNode;
+    return (FX_POSITION) pNewNode;
+}
+void CFX_PtrList::RemoveAt(FX_POSITION position)
+{
+    CNode* pOldNode = (CNode*) position;
+    if (pOldNode == m_pNodeHead) {
+        m_pNodeHead = pOldNode->pNext;
+    } else {
+        pOldNode->pPrev->pNext = pOldNode->pNext;
+    }
+    if (pOldNode == m_pNodeTail) {
+        m_pNodeTail = pOldNode->pPrev;
+    } else {
+        pOldNode->pNext->pPrev = pOldNode->pPrev;
+    }
+    FreeNode(pOldNode);
+}
+void CFX_PtrList::FreeNode(CFX_PtrList::CNode* pNode)
+{
+    pNode->pNext = m_pNodeFree;
+    m_pNodeFree = pNode;
+    m_nCount--;
+    if (m_nCount == 0) {
+        RemoveAll();
+    }
+}
+void CFX_PtrList::RemoveAll()
+{
+    m_nCount = 0;
+    m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
+    m_pBlocks->FreeDataChain();
+    m_pBlocks = NULL;
+}
+CFX_PtrList::CNode*
+CFX_PtrList::NewNode(CFX_PtrList::CNode* pPrev, CFX_PtrList::CNode* pNext)
+{
+    if (m_pNodeFree == NULL) {
+        CFX_Plex* pNewBlock = CFX_Plex::Create(m_pBlocks, m_nBlockSize, sizeof(CNode));
+        CNode* pNode = (CNode*)pNewBlock->data();
+        pNode += m_nBlockSize - 1;
+        for (int i = m_nBlockSize - 1; i >= 0; i--, pNode--) {
+            pNode->pNext = m_pNodeFree;
+            m_pNodeFree = pNode;
+        }
+    }
+    ASSERT(m_pNodeFree != NULL);
+    CFX_PtrList::CNode* pNode = m_pNodeFree;
+    m_pNodeFree = m_pNodeFree->pNext;
+    pNode->pPrev = pPrev;
+    pNode->pNext = pNext;
+    m_nCount++;
+    ASSERT(m_nCount > 0);
+    pNode->data = 0;
+    return pNode;
+}
+CFX_PtrList::~CFX_PtrList()
+{
+    RemoveAll();
+    ASSERT(m_nCount == 0);
+}
+FX_POSITION CFX_PtrList::FindIndex(int nIndex) const
+{
+    if (nIndex >= m_nCount || nIndex < 0) {
+        return NULL;
+    }
+    CNode* pNode = m_pNodeHead;
+    while (nIndex--) {
+        pNode = pNode->pNext;
+    }
+    return (FX_POSITION) pNode;
+}
+FX_POSITION CFX_PtrList::Find(void* searchValue, FX_POSITION startAfter) const
+{
+    CNode* pNode = (CNode*) startAfter;
+    if (pNode == NULL) {
+        pNode = m_pNodeHead;
+    } else {
+        pNode = pNode->pNext;
+    }
+    for (; pNode != NULL; pNode = pNode->pNext)
+        if (pNode->data == searchValue) {
+            return (FX_POSITION) pNode;
+        }
+    return NULL;
+}