 Chromium Code Reviews
 Chromium Code Reviews Issue 1408063016:
  Fix a leak in CPDF_Type3Font::LoadChar().  (Closed) 
  Base URL: https://pdfium.googlesource.com/pdfium@parser_b268
    
  
    Issue 1408063016:
  Fix a leak in CPDF_Type3Font::LoadChar().  (Closed) 
  Base URL: https://pdfium.googlesource.com/pdfium@parser_b268| OLD | NEW | 
|---|---|
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 
| 6 | 6 | 
| 7 #include "../../../include/fpdfapi/fpdf_module.h" | 7 #include "../../../include/fpdfapi/fpdf_module.h" | 
| 8 #include "../../../include/fpdfapi/fpdf_page.h" | 8 #include "../../../include/fpdfapi/fpdf_page.h" | 
| 9 #include "../../../include/fpdfapi/fpdf_pageobj.h" | 9 #include "../../../include/fpdfapi/fpdf_pageobj.h" | 
| 10 #include "../../../include/fpdfapi/fpdf_resource.h" | 10 #include "../../../include/fpdfapi/fpdf_resource.h" | 
| (...skipping 1625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1636 } | 1636 } | 
| 1637 } | 1637 } | 
| 1638 if (bGotOne) { | 1638 if (bGotOne) { | 
| 1639 return; | 1639 return; | 
| 1640 } | 1640 } | 
| 1641 } | 1641 } | 
| 1642 for (int charcode = 0; charcode < 256; charcode++) { | 1642 for (int charcode = 0; charcode < 256; charcode++) { | 
| 1643 m_GlyphIndex[charcode] = charcode; | 1643 m_GlyphIndex[charcode] = charcode; | 
| 1644 } | 1644 } | 
| 1645 } | 1645 } | 
| 1646 CPDF_Type3Font::CPDF_Type3Font() : CPDF_SimpleFont(PDFFONT_TYPE3) { | 1646 | 
| 1647 m_pPageResources = NULL; | 1647 CPDF_Type3Font::CPDF_Type3Font() | 
| 1648 FXSYS_memset(m_CharWidthL, 0, sizeof m_CharWidthL); | 1648 : CPDF_SimpleFont(PDFFONT_TYPE3), | 
| 1649 m_pCharProcs(nullptr), | |
| 1650 m_pPageResources(nullptr), | |
| 1651 m_pFontResources(nullptr) { | |
| 1652 FXSYS_memset(m_CharWidthL, 0, sizeof(m_CharWidthL)); | |
| 1649 } | 1653 } | 
| 1654 | |
| 1650 CPDF_Type3Font::~CPDF_Type3Font() { | 1655 CPDF_Type3Font::~CPDF_Type3Font() { | 
| 1651 FX_POSITION pos = m_CacheMap.GetStartPosition(); | 1656 for (auto it : m_CacheMap) | 
| 1652 while (pos) { | 1657 delete it.second; | 
| 1653 void* key; | |
| 1654 void* value; | |
| 1655 m_CacheMap.GetNextAssoc(pos, key, value); | |
| 1656 delete (CPDF_Type3Char*)value; | |
| 1657 } | |
| 1658 m_CacheMap.RemoveAll(); | |
| 1659 pos = m_DeletedMap.GetStartPosition(); | |
| 1660 while (pos) { | |
| 1661 void* key; | |
| 1662 void* value; | |
| 1663 m_DeletedMap.GetNextAssoc(pos, key, value); | |
| 1664 delete (CPDF_Type3Char*)key; | |
| 1665 } | |
| 1666 } | 1658 } | 
| 1659 | |
| 1667 FX_BOOL CPDF_Type3Font::_Load() { | 1660 FX_BOOL CPDF_Type3Font::_Load() { | 
| 1668 m_pFontResources = m_pFontDict->GetDict(FX_BSTRC("Resources")); | 1661 m_pFontResources = m_pFontDict->GetDict(FX_BSTRC("Resources")); | 
| 1669 CPDF_Array* pMatrix = m_pFontDict->GetArray(FX_BSTRC("FontMatrix")); | 1662 CPDF_Array* pMatrix = m_pFontDict->GetArray(FX_BSTRC("FontMatrix")); | 
| 1670 FX_FLOAT xscale = 1.0f, yscale = 1.0f; | 1663 FX_FLOAT xscale = 1.0f, yscale = 1.0f; | 
| 1671 if (pMatrix) { | 1664 if (pMatrix) { | 
| 1672 m_FontMatrix = pMatrix->GetMatrix(); | 1665 m_FontMatrix = pMatrix->GetMatrix(); | 
| 1673 xscale = m_FontMatrix.a; | 1666 xscale = m_FontMatrix.a; | 
| 1674 yscale = m_FontMatrix.d; | 1667 yscale = m_FontMatrix.d; | 
| 1675 } | 1668 } | 
| 1676 CPDF_Array* pBBox = m_pFontDict->GetArray(FX_BSTRC("FontBBox")); | 1669 CPDF_Array* pBBox = m_pFontDict->GetArray(FX_BSTRC("FontBBox")); | 
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1707 m_Encoding.m_Unicodes[i] = i; | 1700 m_Encoding.m_Unicodes[i] = i; | 
| 1708 } | 1701 } | 
| 1709 } | 1702 } | 
| 1710 } | 1703 } | 
| 1711 } | 1704 } | 
| 1712 return TRUE; | 1705 return TRUE; | 
| 1713 } | 1706 } | 
| 1714 void CPDF_Type3Font::CheckType3FontMetrics() { | 1707 void CPDF_Type3Font::CheckType3FontMetrics() { | 
| 1715 CheckFontMetrics(); | 1708 CheckFontMetrics(); | 
| 1716 } | 1709 } | 
| 1710 | |
| 1717 CPDF_Type3Char* CPDF_Type3Font::LoadChar(FX_DWORD charcode, int level) { | 1711 CPDF_Type3Char* CPDF_Type3Font::LoadChar(FX_DWORD charcode, int level) { | 
| 1718 if (level >= _FPDF_MAX_TYPE3_FORM_LEVEL_) | 1712 if (level >= _FPDF_MAX_TYPE3_FORM_LEVEL_) | 
| 1719 return nullptr; | 1713 return nullptr; | 
| 1720 | 1714 | 
| 1721 CPDF_Type3Char* pChar = nullptr; | 1715 { | 
| 
Tom Sepez
2015/11/08 04:46:29
Why { here?  Can't you just re-assign this at 1748
 
Lei Zhang
2015/11/09 20:27:26
They are unrelated so I didn't want to reuse the s
 | |
| 1722 if (m_CacheMap.Lookup((void*)(uintptr_t)charcode, (void*&)pChar)) { | 1716 auto it = m_CacheMap.find(charcode); | 
| 1723 if (pChar->m_bPageRequired && m_pPageResources) { | 1717 if (it != m_CacheMap.end()) { | 
| 1724 delete pChar; | 1718 CPDF_Type3Char* pCachedChar = it->second; | 
| 1725 m_CacheMap.RemoveKey((void*)(uintptr_t)charcode); | 1719 if (pCachedChar->m_bPageRequired && m_pPageResources) { | 
| 1726 return LoadChar(charcode, level + 1); | 1720 delete pCachedChar; | 
| 1721 m_CacheMap.erase(it); | |
| 1722 return LoadChar(charcode, level + 1); | |
| 1723 } | |
| 1724 return pCachedChar; | |
| 1727 } | 1725 } | 
| 1728 return pChar; | |
| 1729 } | 1726 } | 
| 1727 | |
| 1730 const FX_CHAR* name = | 1728 const FX_CHAR* name = | 
| 1731 GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode); | 1729 GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode); | 
| 1732 if (!name) | 1730 if (!name) | 
| 1733 return nullptr; | 1731 return nullptr; | 
| 1734 | 1732 | 
| 1735 CPDF_Stream* pStream = | 1733 CPDF_Stream* pStream = | 
| 1736 ToStream(m_pCharProcs ? m_pCharProcs->GetElementValue(name) : nullptr); | 1734 ToStream(m_pCharProcs ? m_pCharProcs->GetElementValue(name) : nullptr); | 
| 1737 if (!pStream) | 1735 if (!pStream) | 
| 1738 return nullptr; | 1736 return nullptr; | 
| 1739 | 1737 | 
| 1740 pChar = new CPDF_Type3Char; | 1738 nonstd::unique_ptr<CPDF_Type3Char> pNewChar(new CPDF_Type3Char); | 
| 1741 pChar->m_pForm = new CPDF_Form( | 1739 pNewChar->m_pForm = new CPDF_Form( | 
| 
Tom Sepez
2015/11/08 04:46:29
Pity the constructor doesn't set m_pForm.
 
Lei Zhang
2015/11/09 20:27:26
Done.
 | |
| 1742 m_pDocument, m_pFontResources ? m_pFontResources : m_pPageResources, | 1740 m_pDocument, m_pFontResources ? m_pFontResources : m_pPageResources, | 
| 1743 pStream, nullptr); | 1741 pStream, nullptr); | 
| 1744 pChar->m_pForm->ParseContent(nullptr, nullptr, pChar, nullptr, level + 1); | 1742 | 
| 1743 // This can trigger recursion into this method. The content of |m_CacheMap| | |
| 1744 // can change as a result. Thus after it returns, check the cache again for | |
| 1745 // a cache hit. | |
| 1746 pNewChar->m_pForm->ParseContent(nullptr, nullptr, pNewChar.get(), nullptr, | |
| 1747 level + 1); | |
| 1748 auto it = m_CacheMap.find(charcode); | |
| 1749 if (it != m_CacheMap.end()) | |
| 1750 return it->second; | |
| 1751 | |
| 1745 FX_FLOAT scale = m_FontMatrix.GetXUnit(); | 1752 FX_FLOAT scale = m_FontMatrix.GetXUnit(); | 
| 1746 pChar->m_Width = (int32_t)(pChar->m_Width * scale + 0.5f); | 1753 pNewChar->m_Width = (int32_t)(pNewChar->m_Width * scale + 0.5f); | 
| 1747 FX_RECT& rcBBox = pChar->m_BBox; | 1754 FX_RECT& rcBBox = pNewChar->m_BBox; | 
| 1748 CFX_FloatRect char_rect( | 1755 CFX_FloatRect char_rect( | 
| 1749 (FX_FLOAT)rcBBox.left / 1000.0f, (FX_FLOAT)rcBBox.bottom / 1000.0f, | 1756 (FX_FLOAT)rcBBox.left / 1000.0f, (FX_FLOAT)rcBBox.bottom / 1000.0f, | 
| 1750 (FX_FLOAT)rcBBox.right / 1000.0f, (FX_FLOAT)rcBBox.top / 1000.0f); | 1757 (FX_FLOAT)rcBBox.right / 1000.0f, (FX_FLOAT)rcBBox.top / 1000.0f); | 
| 1751 if (rcBBox.right <= rcBBox.left || rcBBox.bottom >= rcBBox.top) { | 1758 if (rcBBox.right <= rcBBox.left || rcBBox.bottom >= rcBBox.top) | 
| 1752 char_rect = pChar->m_pForm->CalcBoundingBox(); | 1759 char_rect = pNewChar->m_pForm->CalcBoundingBox(); | 
| 1753 } | 1760 | 
| 1754 char_rect.Transform(&m_FontMatrix); | 1761 char_rect.Transform(&m_FontMatrix); | 
| 1755 rcBBox.left = FXSYS_round(char_rect.left * 1000); | 1762 rcBBox.left = FXSYS_round(char_rect.left * 1000); | 
| 1756 rcBBox.right = FXSYS_round(char_rect.right * 1000); | 1763 rcBBox.right = FXSYS_round(char_rect.right * 1000); | 
| 1757 rcBBox.top = FXSYS_round(char_rect.top * 1000); | 1764 rcBBox.top = FXSYS_round(char_rect.top * 1000); | 
| 1758 rcBBox.bottom = FXSYS_round(char_rect.bottom * 1000); | 1765 rcBBox.bottom = FXSYS_round(char_rect.bottom * 1000); | 
| 1759 m_CacheMap.SetAt((void*)(uintptr_t)charcode, pChar); | 1766 | 
| 1760 if (pChar->m_pForm->CountObjects() == 0) { | 1767 FXSYS_assert(m_CacheMap.find(charcode) == m_CacheMap.end()); | 
| 1761 delete pChar->m_pForm; | 1768 CPDF_Type3Char* pCachedChar = pNewChar.release(); | 
| 1762 pChar->m_pForm = nullptr; | 1769 m_CacheMap[charcode] = pCachedChar; | 
| 1770 if (pCachedChar->m_pForm->CountObjects() == 0) { | |
| 1771 delete pCachedChar->m_pForm; | |
| 1772 pCachedChar->m_pForm = nullptr; | |
| 1763 } | 1773 } | 
| 1764 return pChar; | 1774 return pCachedChar; | 
| 1765 } | 1775 } | 
| 1776 | |
| 1766 int CPDF_Type3Font::GetCharWidthF(FX_DWORD charcode, int level) { | 1777 int CPDF_Type3Font::GetCharWidthF(FX_DWORD charcode, int level) { | 
| 1767 if (charcode > 0xff) { | 1778 if (charcode > FX_ArraySize(m_CharWidthL) - 1) | 
| 
Tom Sepez
2015/11/08 04:46:29
or just >= and lose the -1.
 
Lei Zhang
2015/11/09 20:27:26
Done.
 | |
| 1768 charcode = 0; | 1779 charcode = 0; | 
| 1769 } | 1780 | 
| 1770 if (m_CharWidthL[charcode]) { | 1781 if (m_CharWidthL[charcode]) | 
| 1771 return m_CharWidthL[charcode]; | 1782 return m_CharWidthL[charcode]; | 
| 1772 } | 1783 | 
| 1773 CPDF_Type3Char* pChar = LoadChar(charcode, level); | 1784 const CPDF_Type3Char* pChar = LoadChar(charcode, level); | 
| 1774 if (pChar == NULL) { | 1785 return pChar ? pChar->m_Width : 0; | 
| 1775 return 0; | |
| 1776 } | |
| 1777 return pChar->m_Width; | |
| 1778 } | 1786 } | 
| 1787 | |
| 1779 void CPDF_Type3Font::GetCharBBox(FX_DWORD charcode, FX_RECT& rect, int level) { | 1788 void CPDF_Type3Font::GetCharBBox(FX_DWORD charcode, FX_RECT& rect, int level) { | 
| 1780 CPDF_Type3Char* pChar = LoadChar(charcode, level); | 1789 const CPDF_Type3Char* pChar = LoadChar(charcode, level); | 
| 1781 if (pChar == NULL) { | 1790 if (!pChar) { | 
| 1782 rect.left = rect.right = rect.top = rect.bottom = 0; | 1791 rect.left = rect.right = rect.top = rect.bottom = 0; | 
| 
Tom Sepez
2015/11/08 04:46:29
nit: one per line.
 
Lei Zhang
2015/11/09 20:27:26
Done.
 | |
| 1783 return; | 1792 return; | 
| 1784 } | 1793 } | 
| 1785 rect = pChar->m_BBox; | 1794 rect = pChar->m_BBox; | 
| 1786 } | 1795 } | 
| 1796 | |
| 1787 CPDF_Type3Char::CPDF_Type3Char() { | 1797 CPDF_Type3Char::CPDF_Type3Char() { | 
| 1788 m_pForm = NULL; | 1798 m_pForm = NULL; | 
| 1789 m_pBitmap = NULL; | 1799 m_pBitmap = NULL; | 
| 1790 m_bPageRequired = FALSE; | 1800 m_bPageRequired = FALSE; | 
| 1791 m_bColored = FALSE; | 1801 m_bColored = FALSE; | 
| 1792 } | 1802 } | 
| 1793 CPDF_Type3Char::~CPDF_Type3Char() { | 1803 CPDF_Type3Char::~CPDF_Type3Char() { | 
| 1794 delete m_pForm; | 1804 delete m_pForm; | 
| 1795 delete m_pBitmap; | 1805 delete m_pBitmap; | 
| 1796 } | 1806 } | 
| OLD | NEW |