Store the address of the page data map's value for proper referencing.

CPDF_Pattern objects are counted and maintained in m_PatternedMap.
When a CPDF_Pattern object "pattern" is deleted, it's address is marked as NULL in m_PatternMap.
This patch stores the address of CPDF_Pattern's adderss in all objects that references "pattern",
to ensure valid referencing after deletion.

BUG=416319, 419976, 418392
R=tsepez@chromium.org

Review URL: https://codereview.chromium.org/656753002
diff --git a/core/include/fpdfapi/fpdf_resource.h b/core/include/fpdfapi/fpdf_resource.h
index 7bad015..54e1c97 100644
--- a/core/include/fpdfapi/fpdf_resource.h
+++ b/core/include/fpdfapi/fpdf_resource.h
@@ -38,6 +38,28 @@
 typedef struct FT_FaceRec_* FXFT_Face;
 class CFX_CTTGSUBTable;
 class CPDF_Page;
+
+template <class ObjClass> class CPDF_CountedObject : public CFX_Object
+{
+public:
+    ObjClass	m_Obj;
+    FX_DWORD	m_nCount;
+};
+typedef CPDF_CountedObject<CPDF_Font*>          CPDF_CountedFont;
+typedef CPDF_CountedObject<CPDF_ColorSpace*>    CPDF_CountedColorSpace;
+typedef CPDF_CountedObject<CPDF_Pattern*>       CPDF_CountedPattern;
+typedef CPDF_CountedObject<CPDF_Image*>         CPDF_CountedImage;
+typedef CPDF_CountedObject<CPDF_IccProfile*>    CPDF_CountedICCProfile;
+typedef CPDF_CountedObject<CPDF_StreamAcc*>     CPDF_CountedStreamAcc;
+
+
+typedef CFX_MapPtrTemplate<CPDF_Dictionary*, CPDF_CountedFont*>     CPDF_FontMap;
+typedef CFX_MapPtrTemplate<CPDF_Object*, CPDF_CountedColorSpace*>   CPDF_ColorSpaceMap;
+typedef CFX_MapPtrTemplate<CPDF_Object*, CPDF_CountedPattern*>      CPDF_PatternMap;
+typedef CFX_MapPtrTemplate<FX_DWORD, CPDF_CountedImage*>            CPDF_ImageMap;
+typedef CFX_MapPtrTemplate<CPDF_Stream*, CPDF_CountedICCProfile*>   CPDF_IccProfileMap;
+typedef CFX_MapPtrTemplate<CPDF_Stream*, CPDF_CountedStreamAcc*>    CPDF_FontFileMap;
+
 #define PDFFONT_TYPE1			1
 #define PDFFONT_TRUETYPE		2
 #define PDFFONT_TYPE3			3
@@ -790,8 +812,9 @@
 
     int					m_ShadingType;
 
-    CPDF_ColorSpace*	m_pCS;
+    CPDF_ColorSpace*	m_pCS; // Still keep m_pCS as some CPDF_ColorSpace (name object) are not managed as counted objects. Refer to CPDF_DocPageData::GetColorSpace.
 
+    CPDF_CountedColorSpace*	m_pCountedCS;
 
     CPDF_Function*		m_pFunctions[4];
 
diff --git a/core/src/fpdfapi/fpdf_page/fpdf_page_colors.cpp b/core/src/fpdfapi/fpdf_page/fpdf_page_colors.cpp
index c522dcd..5266c1a 100644
--- a/core/src/fpdfapi/fpdf_page/fpdf_page_colors.cpp
+++ b/core/src/fpdfapi/fpdf_page/fpdf_page_colors.cpp
@@ -760,6 +760,7 @@
     }
     virtual void		EnableStdConversion(FX_BOOL bEnabled);
     CPDF_ColorSpace*	m_pBaseCS;
+    CPDF_CountedColorSpace*     m_pCountedBaseCS;
     int					m_nBaseComponents;
     int					m_MaxIndex;
     CFX_ByteString		m_Table;
@@ -768,6 +769,7 @@
 CPDF_IndexedCS::CPDF_IndexedCS()
 {
     m_pBaseCS = NULL;
+    m_pCountedBaseCS = NULL;
     m_Family = PDFCS_INDEXED;
     m_nComponents = 1;
     m_pCompMinMax = NULL;
@@ -777,6 +779,10 @@
     if (m_pCompMinMax) {
         FX_Free(m_pCompMinMax);
     }
+    CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->m_Obj : NULL;
+    if (pCS && m_pDocument) {
+        m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
+    }
 }
 FX_BOOL CPDF_IndexedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
 {
@@ -792,6 +798,7 @@
     if (m_pBaseCS == NULL) {
         return FALSE;
     }
+    m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray());
     m_nBaseComponents = m_pBaseCS->CountComponents();
     m_pCompMinMax = FX_Alloc(FX_FLOAT, m_nBaseComponents * 2);
     FX_FLOAT defvalue;
@@ -845,6 +852,7 @@
 #define MAX_PATTERN_COLORCOMPS	16
 typedef struct _PatternValue {
     CPDF_Pattern*	m_pPattern;
+    CPDF_CountedPattern*	m_pCountedPattern;
     int				m_nComps;
     FX_FLOAT		m_Comps[MAX_PATTERN_COLORCOMPS];
 } PatternValue;
@@ -853,9 +861,14 @@
     m_Family = PDFCS_PATTERN;
     m_pBaseCS = NULL;
     m_nComponents = 1;
+    m_pCountedBaseCS = NULL;
 }
 CPDF_PatternCS::~CPDF_PatternCS()
 {
+    CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->m_Obj : NULL;
+    if (pCS && m_pDocument) {
+	    m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
+    }
 }
 FX_BOOL CPDF_PatternCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray)
 {
@@ -869,6 +882,7 @@
         if (m_pBaseCS->GetFamily() == PDFCS_PATTERN) {
             return FALSE;
         }
+        m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray());
         m_nComponents = m_pBaseCS->CountComponents() + 1;
         if (m_pBaseCS->CountComponents() > MAX_PATTERN_COLORCOMPS) {
             return FALSE;
@@ -1291,10 +1305,10 @@
     }
     if (m_pCS->GetFamily() == PDFCS_PATTERN) {
         PatternValue* pvalue = (PatternValue*)m_pBuffer;
-        CPDF_Pattern* pPattern = pvalue->m_pPattern;
+        CPDF_Pattern* pPattern = pvalue->m_pCountedPattern ? pvalue->m_pCountedPattern->m_Obj : NULL;
         if (pPattern && pPattern->m_pDocument) {
             CPDF_DocPageData *pPageData = pPattern->m_pDocument->GetPageData();
-            if (pPageData && !pPageData->IsForceClear()) {
+            if (pPageData) {
                 pPageData->ReleasePattern(pPattern->m_pPatternObj);
             }
         }
@@ -1348,10 +1362,11 @@
         m_pCS = CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
         m_pBuffer = m_pCS->CreateBuf();
     }
+    CPDF_DocPageData *pDocPageData = NULL;
     PatternValue* pvalue = (PatternValue*)m_pBuffer;
     if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) {
-        CPDF_DocPageData *pDocPageData = pvalue->m_pPattern->m_pDocument->GetPageData();
-        if (pDocPageData && !pDocPageData->IsForceClear()) {
+        pDocPageData = pvalue->m_pPattern->m_pDocument->GetPageData();
+        if (pDocPageData) {
             pDocPageData->ReleasePattern(pvalue->m_pPattern->m_pPatternObj);
         }
     }
@@ -1360,6 +1375,14 @@
     if (ncomps) {
         FXSYS_memcpy32(pvalue->m_Comps, comps, ncomps * sizeof(FX_FLOAT));
     }
+    pvalue->m_pCountedPattern = NULL;

+    if (pPattern && pPattern->m_pDocument)

+    {

+        if (!pDocPageData) {

+            pDocPageData = pPattern->m_pDocument->GetPageData();

+        }

+        pvalue->m_pCountedPattern = pDocPageData->FindPatternPtr(pPattern->m_pPatternObj);

+    }
 }
 void CPDF_Color::Copy(const CPDF_Color* pSrc)
 {
diff --git a/core/src/fpdfapi/fpdf_page/fpdf_page_doc.cpp b/core/src/fpdfapi/fpdf_page/fpdf_page_doc.cpp
index 8e578f6..fe5665d 100644
--- a/core/src/fpdfapi/fpdf_page/fpdf_page_doc.cpp
+++ b/core/src/fpdfapi/fpdf_page/fpdf_page_doc.cpp
@@ -147,15 +147,52 @@
 {
     Clear(FALSE);
     Clear(TRUE);
+    FX_POSITION pos = m_PatternMap.GetStartPosition();

+    while (pos)

+    {

+        CPDF_Object* ptObj;

+        CPDF_CountedObject<CPDF_Pattern*>* ptData;

+        m_PatternMap.GetNextAssoc(pos, ptObj, ptData);

+        delete ptData;

+    }

+    m_PatternMap.RemoveAll();

+    pos = m_FontMap.GetStartPosition();

+    while (pos)

+    {

+        CPDF_Dictionary* fontDict;

+        CPDF_CountedObject<CPDF_Font*>* fontData;

+        m_FontMap.GetNextAssoc(pos, fontDict, fontData);

+        delete fontData;

+    }

+    m_FontMap.RemoveAll();

+    pos = m_ColorSpaceMap.GetStartPosition();

+    while (pos)

+    {

+        CPDF_Object* csKey;

+        CPDF_CountedObject<CPDF_ColorSpace*>* csData;

+        m_ColorSpaceMap.GetNextAssoc(pos, csKey, csData);

+        delete csData;

+    }

+    m_ColorSpaceMap.RemoveAll();
 }
 void CPDF_DocPageData::Clear(FX_BOOL bForceRelease)
 {
     FX_POSITION pos;
-
     m_bForceClear = bForceRelease;
-
-    // Release objects saved in the resource maps like font map and color space map.
-    // The compound objects shall be released before simple ones.
+    pos = m_PatternMap.GetStartPosition();
+    while (pos) {
+        CPDF_Object* ptObj;
+        CPDF_CountedObject<CPDF_Pattern*>* ptData;
+        m_PatternMap.GetNextAssoc(pos, ptObj, ptData);
+        if (!ptData->m_Obj) {
+            continue;
+        }
+        if (bForceRelease || ptData->m_nCount < 2) {
+            ptData->m_Obj->SetForceClear(bForceRelease);
+            delete ptData->m_Obj;
+            ptData->m_Obj = NULL;
+        }
+    }
     pos = m_FontMap.GetStartPosition();
     while (pos) {
         CPDF_Dictionary* fontDict;
@@ -203,7 +240,6 @@
                 }
             }
             delete ipData->m_Obj;
-            ipData->m_Obj = NULL;
             delete ipData;
             m_IccProfileMap.RemoveKey(ipKey);
         }
@@ -218,25 +254,10 @@
         }
         if (bForceRelease || ftData->m_nCount < 2) {
             delete ftData->m_Obj;
-            ftData->m_Obj = NULL;
             delete ftData;
             m_FontFileMap.RemoveKey(ftKey);
         }
     }
-    pos = m_PatternMap.GetStartPosition();
-    while (pos) {
-        CPDF_Object* ptObj;
-        CPDF_CountedObject<CPDF_Pattern*>* ptData;
-        m_PatternMap.GetNextAssoc(pos, ptObj, ptData);
-        if (!ptData->m_Obj) {
-            continue;
-        }
-        if (bForceRelease || ptData->m_nCount < 2) {
-            ptData->m_Obj->SetForceClear(bForceRelease);
-            delete ptData->m_Obj;
-            ptData->m_Obj = NULL;
-        }
-    }
     pos = m_ImageMap.GetStartPosition();
     while (pos) {
         FX_DWORD objNum;
@@ -247,7 +268,6 @@
         }
         if (bForceRelease || imageData->m_nCount < 2) {
             delete imageData->m_Obj;
-            imageData->m_Obj = NULL;
             delete imageData;
             m_ImageMap.RemoveKey(objNum);
         }
@@ -653,4 +673,24 @@
         return;
     }
     PDF_DocPageData_Release<CPDF_Stream*, CPDF_StreamAcc*>(m_FontFileMap, pFontStream, NULL, bForce);
+}

+CPDF_CountedColorSpace* CPDF_DocPageData::FindColorSpacePtr(CPDF_Object* pCSObj) const

+{

+    if (!pCSObj) return NULL;

+    CPDF_CountedObject<CPDF_ColorSpace*>* csData;

+    if (m_ColorSpaceMap.Lookup(pCSObj, csData))

+    {

+        return csData;

+    }

+    return NULL;

 }
+CPDF_CountedPattern* CPDF_DocPageData::FindPatternPtr(CPDF_Object* pPatternObj) const

+{

+    if (!pPatternObj) return NULL;

+    CPDF_CountedObject<CPDF_Pattern*>* ptData;

+    if (m_PatternMap.Lookup(pPatternObj, ptData))

+    {

+        return ptData;

+    }

+    return NULL;

+}

diff --git a/core/src/fpdfapi/fpdf_page/fpdf_page_pattern.cpp b/core/src/fpdfapi/fpdf_page/fpdf_page_pattern.cpp
index 67ea4fe..467ef9b 100644
--- a/core/src/fpdfapi/fpdf_page/fpdf_page_pattern.cpp
+++ b/core/src/fpdfapi/fpdf_page/fpdf_page_pattern.cpp
@@ -83,6 +83,7 @@
     for (int i = 0; i < 4; i ++) {
         m_pFunctions[i] = NULL;
     }
+    m_pCountedCS = NULL;
 }
 CPDF_ShadingPattern::~CPDF_ShadingPattern()
 {
@@ -96,12 +97,13 @@
         }
         m_pFunctions[i] = NULL;
     }
-    CPDF_ColorSpace* pCS = m_pCS;
-    if (!m_bForceClear && pCS && m_pDocument) {
+    CPDF_ColorSpace* pCS = m_pCountedCS ? m_pCountedCS->m_Obj : NULL;
+    if (pCS && m_pDocument) {
         m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray());
     }
     m_ShadingType = 0;
     m_pCS = NULL;
+    m_pCountedCS = NULL;
     m_nFuncs = 0;
 }
 FX_BOOL CPDF_ShadingPattern::Load()
@@ -141,6 +143,9 @@
     }
     CPDF_DocPageData* pDocPageData = m_pDocument->GetPageData();
     m_pCS = pDocPageData->GetColorSpace(pCSObj, NULL);
+    if (m_pCS) {

+        m_pCountedCS = pDocPageData->FindColorSpacePtr(m_pCS->GetArray());
+    }
     m_ShadingType = pShadingDict->GetInteger(FX_BSTRC("ShadingType"));
     return TRUE;
 }
diff --git a/core/src/fpdfapi/fpdf_page/pageint.h b/core/src/fpdfapi/fpdf_page/pageint.h
index f79b8d3..cc35dbe 100644
--- a/core/src/fpdfapi/fpdf_page/pageint.h
+++ b/core/src/fpdfapi/fpdf_page/pageint.h
@@ -364,18 +364,7 @@
     FX_FLOAT				m_TextX, m_TextY, m_TextLineX, m_TextLineY;
     FX_FLOAT				m_TextLeading, m_TextRise, m_TextHorzScale;
 };
-template <class ObjClass> class CPDF_CountedObject : public CFX_Object
-{
-public:
-    ObjClass	m_Obj;
-    FX_DWORD	m_nCount;
-};
-typedef CFX_MapPtrTemplate<CPDF_Dictionary*, CPDF_CountedObject<CPDF_Font*>*>		CPDF_FontMap;
-typedef CFX_MapPtrTemplate<CPDF_Object*, CPDF_CountedObject<CPDF_ColorSpace*>*>		CPDF_ColorSpaceMap;
-typedef CFX_MapPtrTemplate<CPDF_Object*, CPDF_CountedObject<CPDF_Pattern*>*>		CPDF_PatternMap;
-typedef CFX_MapPtrTemplate<FX_DWORD, CPDF_CountedObject<CPDF_Image*>*>				CPDF_ImageMap;
-typedef CFX_MapPtrTemplate<CPDF_Stream*, CPDF_CountedObject<CPDF_IccProfile*>*>		CPDF_IccProfileMap;
-typedef CFX_MapPtrTemplate<CPDF_Stream*, CPDF_CountedObject<CPDF_StreamAcc*>*>		CPDF_FontFileMap;
+
 template <class KeyType, class ValueType>
 KeyType PDF_DocPageData_FindValue(const CFX_MapPtrTemplate<KeyType, CPDF_CountedObject<ValueType>*> &map, ValueType findValue, CPDF_CountedObject<ValueType>*& findData)
 {
@@ -430,7 +419,9 @@
     void                        ReleaseIccProfile(CPDF_Stream* pIccProfileStream, CPDF_IccProfile* pIccProfile);
     CPDF_StreamAcc*             GetFontFileStreamAcc(CPDF_Stream* pFontStream);
     void                        ReleaseFontFileStreamAcc(CPDF_Stream* pFontStream, FX_BOOL bForce = FALSE);
-    FX_BOOL                     IsForceClear() const {return m_bForceClear;}
+    FX_BOOL                     IsForceClear() const {return m_bForceClear;}

+    CPDF_CountedColorSpace*     FindColorSpacePtr(CPDF_Object* pCSObj) const;

+    CPDF_CountedPattern*        FindPatternPtr(CPDF_Object* pPatternObj) const;
 
     CPDF_Document*              m_pPDFDoc;
     CPDF_FontMap                m_FontMap;
@@ -497,6 +488,7 @@
         return m_pBaseCS;
     }
     CPDF_ColorSpace*	m_pBaseCS;
+    CPDF_CountedColorSpace*	m_pCountedBaseCS;
 };
 #define	MAX_PAGE_OBJECTS_UNIFY_NAMING				4096
 class CPDF_ResourceNaming : public CFX_Object