OLD | NEW |
1 // Copyright 2016 PDFium Authors. All rights reserved. | 1 // Copyright 2016 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 "core/fpdfapi/fpdf_parser/include/cpdf_parser.h" | 7 #include "core/fpdfapi/fpdf_parser/include/cpdf_parser.h" |
8 | 8 |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 auto saved_it = it++; | 119 auto saved_it = it++; |
120 m_ObjectInfo.erase(saved_it); | 120 m_ObjectInfo.erase(saved_it); |
121 } | 121 } |
122 | 122 |
123 if (!pdfium::ContainsKey(m_ObjectInfo, objnum - 1)) | 123 if (!pdfium::ContainsKey(m_ObjectInfo, objnum - 1)) |
124 m_ObjectInfo[objnum - 1].pos = 0; | 124 m_ObjectInfo[objnum - 1].pos = 0; |
125 } | 125 } |
126 | 126 |
127 void CPDF_Parser::CloseParser() { | 127 void CPDF_Parser::CloseParser() { |
128 m_bVersionUpdated = false; | 128 m_bVersionUpdated = false; |
129 m_pDocument.reset(); | 129 m_pDocument = nullptr; |
130 | 130 |
131 if (m_pTrailer) { | 131 if (m_pTrailer) { |
132 m_pTrailer->Release(); | 132 m_pTrailer->Release(); |
133 m_pTrailer = nullptr; | 133 m_pTrailer = nullptr; |
134 } | 134 } |
135 ReleaseEncryptHandler(); | 135 ReleaseEncryptHandler(); |
136 SetEncryptDictionary(nullptr); | 136 SetEncryptDictionary(nullptr); |
137 | 137 |
138 if (m_bOwnFileRead && m_pSyntax->m_pFileAccess) { | 138 if (m_bOwnFileRead && m_pSyntax->m_pFileAccess) { |
139 m_pSyntax->m_pFileAccess->Release(); | 139 m_pSyntax->m_pFileAccess->Release(); |
(...skipping 11 matching lines...) Expand all Loading... |
151 trailer->Release(); | 151 trailer->Release(); |
152 } | 152 } |
153 m_Trailers.RemoveAll(); | 153 m_Trailers.RemoveAll(); |
154 | 154 |
155 if (m_pLinearized) { | 155 if (m_pLinearized) { |
156 m_pLinearized->Release(); | 156 m_pLinearized->Release(); |
157 m_pLinearized = nullptr; | 157 m_pLinearized = nullptr; |
158 } | 158 } |
159 } | 159 } |
160 | 160 |
161 CPDF_Parser::Error CPDF_Parser::StartParse( | 161 CPDF_Parser::Error CPDF_Parser::StartParse(IFX_FileRead* pFileAccess, |
162 IFX_FileRead* pFileAccess, | 162 CPDF_Document* pDocument) { |
163 std::unique_ptr<CPDF_Document> pDocument) { | |
164 CloseParser(); | 163 CloseParser(); |
165 | 164 |
166 m_bXRefStream = FALSE; | 165 m_bXRefStream = FALSE; |
167 m_LastXRefOffset = 0; | 166 m_LastXRefOffset = 0; |
168 m_bOwnFileRead = true; | 167 m_bOwnFileRead = true; |
169 | 168 |
170 int32_t offset = GetHeaderOffset(pFileAccess); | 169 int32_t offset = GetHeaderOffset(pFileAccess); |
171 if (offset == -1) { | 170 if (offset == -1) { |
172 if (pFileAccess) | 171 if (pFileAccess) |
173 pFileAccess->Release(); | 172 pFileAccess->Release(); |
174 return FORMAT_ERROR; | 173 return FORMAT_ERROR; |
175 } | 174 } |
176 m_pSyntax->InitParser(pFileAccess, offset); | 175 m_pSyntax->InitParser(pFileAccess, offset); |
177 | 176 |
178 uint8_t ch; | 177 uint8_t ch; |
179 if (!m_pSyntax->GetCharAt(5, ch)) | 178 if (!m_pSyntax->GetCharAt(5, ch)) |
180 return FORMAT_ERROR; | 179 return FORMAT_ERROR; |
181 if (std::isdigit(ch)) | 180 if (std::isdigit(ch)) |
182 m_FileVersion = FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch)) * 10; | 181 m_FileVersion = FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch)) * 10; |
183 | 182 |
184 if (!m_pSyntax->GetCharAt(7, ch)) | 183 if (!m_pSyntax->GetCharAt(7, ch)) |
185 return FORMAT_ERROR; | 184 return FORMAT_ERROR; |
186 if (std::isdigit(ch)) | 185 if (std::isdigit(ch)) |
187 m_FileVersion += FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch)); | 186 m_FileVersion += FXSYS_toDecimalDigit(static_cast<FX_WCHAR>(ch)); |
188 | 187 |
189 if (m_pSyntax->m_FileLen < m_pSyntax->m_HeaderOffset + 9) | 188 if (m_pSyntax->m_FileLen < m_pSyntax->m_HeaderOffset + 9) |
190 return FORMAT_ERROR; | 189 return FORMAT_ERROR; |
191 | 190 |
192 m_pSyntax->RestorePos(m_pSyntax->m_FileLen - m_pSyntax->m_HeaderOffset - 9); | 191 m_pSyntax->RestorePos(m_pSyntax->m_FileLen - m_pSyntax->m_HeaderOffset - 9); |
193 m_pDocument = std::move(pDocument); | 192 m_pDocument = pDocument; |
194 | 193 |
195 FX_BOOL bXRefRebuilt = FALSE; | 194 FX_BOOL bXRefRebuilt = FALSE; |
196 if (m_pSyntax->SearchWord("startxref", TRUE, FALSE, 4096)) { | 195 if (m_pSyntax->SearchWord("startxref", TRUE, FALSE, 4096)) { |
197 m_SortedOffset.insert(m_pSyntax->SavePos()); | 196 m_SortedOffset.insert(m_pSyntax->SavePos()); |
198 m_pSyntax->GetKeyword(); | 197 m_pSyntax->GetKeyword(); |
199 | 198 |
200 bool bNumber; | 199 bool bNumber; |
201 CFX_ByteString xrefpos_str = m_pSyntax->GetNextWord(&bNumber); | 200 CFX_ByteString xrefpos_str = m_pSyntax->GetNextWord(&bNumber); |
202 if (!bNumber) | 201 if (!bNumber) |
203 return FORMAT_ERROR; | 202 return FORMAT_ERROR; |
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
758 inside_index++; | 757 inside_index++; |
759 } | 758 } |
760 break; | 759 break; |
761 case 3: | 760 case 3: |
762 if (PDFCharIsWhitespace(byte) || PDFCharIsDelimiter(byte)) { | 761 if (PDFCharIsWhitespace(byte) || PDFCharIsDelimiter(byte)) { |
763 FX_FILESIZE obj_pos = start_pos - m_pSyntax->m_HeaderOffset; | 762 FX_FILESIZE obj_pos = start_pos - m_pSyntax->m_HeaderOffset; |
764 m_SortedOffset.insert(obj_pos); | 763 m_SortedOffset.insert(obj_pos); |
765 last_obj = start_pos; | 764 last_obj = start_pos; |
766 FX_FILESIZE obj_end = 0; | 765 FX_FILESIZE obj_end = 0; |
767 CPDF_Object* pObject = ParseIndirectObjectAtByStrict( | 766 CPDF_Object* pObject = ParseIndirectObjectAtByStrict( |
768 m_pDocument.get(), obj_pos, objnum, &obj_end); | 767 m_pDocument, obj_pos, objnum, &obj_end); |
769 if (CPDF_Stream* pStream = ToStream(pObject)) { | 768 if (CPDF_Stream* pStream = ToStream(pObject)) { |
770 if (CPDF_Dictionary* pDict = pStream->GetDict()) { | 769 if (CPDF_Dictionary* pDict = pStream->GetDict()) { |
771 if ((pDict->KeyExist("Type")) && | 770 if ((pDict->KeyExist("Type")) && |
772 (pDict->GetStringBy("Type") == "XRef" && | 771 (pDict->GetStringBy("Type") == "XRef" && |
773 pDict->KeyExist("Size"))) { | 772 pDict->KeyExist("Size"))) { |
774 CPDF_Object* pRoot = pDict->GetObjectBy("Root"); | 773 CPDF_Object* pRoot = pDict->GetObjectBy("Root"); |
775 if (pRoot && pRoot->GetDict() && | 774 if (pRoot && pRoot->GetDict() && |
776 pRoot->GetDict()->GetObjectBy("Pages")) { | 775 pRoot->GetDict()->GetObjectBy("Pages")) { |
777 if (m_pTrailer) | 776 if (m_pTrailer) |
778 m_pTrailer->Release(); | 777 m_pTrailer->Release(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
821 break; | 820 break; |
822 } | 821 } |
823 break; | 822 break; |
824 | 823 |
825 case ParserState::kTrailer: | 824 case ParserState::kTrailer: |
826 if (inside_index == 7) { | 825 if (inside_index == 7) { |
827 if (PDFCharIsWhitespace(byte) || PDFCharIsDelimiter(byte)) { | 826 if (PDFCharIsWhitespace(byte) || PDFCharIsDelimiter(byte)) { |
828 last_trailer = pos + i - 7; | 827 last_trailer = pos + i - 7; |
829 m_pSyntax->RestorePos(pos + i - m_pSyntax->m_HeaderOffset); | 828 m_pSyntax->RestorePos(pos + i - m_pSyntax->m_HeaderOffset); |
830 | 829 |
831 CPDF_Object* pObj = | 830 CPDF_Object* pObj = m_pSyntax->GetObject(m_pDocument, 0, 0, true); |
832 m_pSyntax->GetObject(m_pDocument.get(), 0, 0, true); | |
833 if (pObj) { | 831 if (pObj) { |
834 if (!pObj->IsDictionary() && !pObj->AsStream()) { | 832 if (!pObj->IsDictionary() && !pObj->AsStream()) { |
835 pObj->Release(); | 833 pObj->Release(); |
836 } else { | 834 } else { |
837 CPDF_Stream* pStream = pObj->AsStream(); | 835 CPDF_Stream* pStream = pObj->AsStream(); |
838 if (CPDF_Dictionary* pTrailer = | 836 if (CPDF_Dictionary* pTrailer = |
839 pStream ? pStream->GetDict() : pObj->AsDictionary()) { | 837 pStream ? pStream->GetDict() : pObj->AsDictionary()) { |
840 if (m_pTrailer) { | 838 if (m_pTrailer) { |
841 CPDF_Object* pRoot = pTrailer->GetObjectBy("Root"); | 839 CPDF_Object* pRoot = pTrailer->GetObjectBy("Root"); |
842 CPDF_Reference* pRef = ToReference(pRoot); | 840 CPDF_Reference* pRef = ToReference(pRoot); |
843 if (!pRoot || | 841 if (!pRoot || |
844 (pRef && IsValidObjectNumber(pRef->GetRefObjNum()) && | 842 (pRef && IsValidObjectNumber(pRef->GetRefObjNum()) && |
845 m_ObjectInfo[pRef->GetRefObjNum()].pos != 0)) { | 843 m_ObjectInfo[pRef->GetRefObjNum()].pos != 0)) { |
846 auto it = pTrailer->begin(); | 844 auto it = pTrailer->begin(); |
847 while (it != pTrailer->end()) { | 845 while (it != pTrailer->end()) { |
848 const CFX_ByteString& key = it->first; | 846 const CFX_ByteString& key = it->first; |
849 CPDF_Object* pElement = it->second; | 847 CPDF_Object* pElement = it->second; |
850 ++it; | 848 ++it; |
851 uint32_t dwObjNum = | 849 uint32_t dwObjNum = |
852 pElement ? pElement->GetObjNum() : 0; | 850 pElement ? pElement->GetObjNum() : 0; |
853 if (dwObjNum) { | 851 if (dwObjNum) { |
854 m_pTrailer->SetAtReference(key, m_pDocument.get(), | 852 m_pTrailer->SetAtReference(key, m_pDocument, |
855 dwObjNum); | 853 dwObjNum); |
856 } else { | 854 } else { |
857 m_pTrailer->SetAt(key, pElement->Clone()); | 855 m_pTrailer->SetAt(key, pElement->Clone()); |
858 } | 856 } |
859 } | 857 } |
860 } | 858 } |
861 pObj->Release(); | 859 pObj->Release(); |
862 } else { | 860 } else { |
863 if (pObj->IsStream()) { | 861 if (pObj->IsStream()) { |
864 m_pTrailer = ToDictionary(pTrailer->Clone()); | 862 m_pTrailer = ToDictionary(pTrailer->Clone()); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
968 if (last_xref != -1 && last_xref > last_obj) | 966 if (last_xref != -1 && last_xref > last_obj) |
969 last_trailer = last_xref; | 967 last_trailer = last_xref; |
970 else if (last_trailer == -1 || last_xref < last_obj) | 968 else if (last_trailer == -1 || last_xref < last_obj) |
971 last_trailer = m_pSyntax->m_FileLen; | 969 last_trailer = m_pSyntax->m_FileLen; |
972 | 970 |
973 m_SortedOffset.insert(last_trailer - m_pSyntax->m_HeaderOffset); | 971 m_SortedOffset.insert(last_trailer - m_pSyntax->m_HeaderOffset); |
974 return m_pTrailer && !m_ObjectInfo.empty(); | 972 return m_pTrailer && !m_ObjectInfo.empty(); |
975 } | 973 } |
976 | 974 |
977 FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, FX_BOOL bMainXRef) { | 975 FX_BOOL CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, FX_BOOL bMainXRef) { |
978 CPDF_Object* pObject = ParseIndirectObjectAt(m_pDocument.get(), *pos, 0); | 976 CPDF_Object* pObject = ParseIndirectObjectAt(m_pDocument, *pos, 0); |
979 if (!pObject) | 977 if (!pObject) |
980 return FALSE; | 978 return FALSE; |
981 | 979 |
982 if (m_pDocument) { | 980 if (m_pDocument) { |
983 CPDF_Dictionary* pRootDict = m_pDocument->GetRoot(); | 981 CPDF_Dictionary* pRootDict = m_pDocument->GetRoot(); |
984 if (pRootDict && pRootDict->GetObjNum() == pObject->m_ObjNum) { | 982 if (pRootDict && pRootDict->GetObjNum() == pObject->m_ObjNum) { |
985 // If |pObject| has an objnum assigned then this will leak as Release() | 983 // If |pObject| has an objnum assigned then this will leak as Release() |
986 // will early exit. | 984 // will early exit. |
987 if (pObject->IsStream()) | 985 if (pObject->IsStream()) |
988 pObject->Release(); | 986 pObject->Release(); |
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1471 | 1469 |
1472 m_pSyntax->RestorePos(SavedPos); | 1470 m_pSyntax->RestorePos(SavedPos); |
1473 return pObj; | 1471 return pObj; |
1474 } | 1472 } |
1475 | 1473 |
1476 CPDF_Dictionary* CPDF_Parser::LoadTrailerV4() { | 1474 CPDF_Dictionary* CPDF_Parser::LoadTrailerV4() { |
1477 if (m_pSyntax->GetKeyword() != "trailer") | 1475 if (m_pSyntax->GetKeyword() != "trailer") |
1478 return nullptr; | 1476 return nullptr; |
1479 | 1477 |
1480 std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>> pObj( | 1478 std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>> pObj( |
1481 m_pSyntax->GetObject(m_pDocument.get(), 0, 0, true)); | 1479 m_pSyntax->GetObject(m_pDocument, 0, 0, true)); |
1482 if (!ToDictionary(pObj.get())) | 1480 if (!ToDictionary(pObj.get())) |
1483 return nullptr; | 1481 return nullptr; |
1484 return pObj.release()->AsDictionary(); | 1482 return pObj.release()->AsDictionary(); |
1485 } | 1483 } |
1486 | 1484 |
1487 uint32_t CPDF_Parser::GetPermissions() const { | 1485 uint32_t CPDF_Parser::GetPermissions() const { |
1488 if (!m_pSecurityHandler) | 1486 if (!m_pSecurityHandler) |
1489 return 0xFFFFFFFF; | 1487 return 0xFFFFFFFF; |
1490 | 1488 |
1491 uint32_t dwPermission = m_pSecurityHandler->GetPermissions(); | 1489 uint32_t dwPermission = m_pSecurityHandler->GetPermissions(); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1543 if (CPDF_Number* pTable = ToNumber(pDict->GetObjectBy("T"))) | 1541 if (CPDF_Number* pTable = ToNumber(pDict->GetObjectBy("T"))) |
1544 m_LastXRefOffset = pTable->GetInteger(); | 1542 m_LastXRefOffset = pTable->GetInteger(); |
1545 | 1543 |
1546 return TRUE; | 1544 return TRUE; |
1547 } | 1545 } |
1548 m_pLinearized->Release(); | 1546 m_pLinearized->Release(); |
1549 m_pLinearized = nullptr; | 1547 m_pLinearized = nullptr; |
1550 return FALSE; | 1548 return FALSE; |
1551 } | 1549 } |
1552 | 1550 |
1553 CPDF_Parser::Error CPDF_Parser::StartLinearizedParse( | 1551 CPDF_Parser::Error CPDF_Parser::StartLinearizedParse(IFX_FileRead* pFileAccess, |
1554 IFX_FileRead* pFileAccess, | 1552 CPDF_Document* pDocument) { |
1555 std::unique_ptr<CPDF_Document> pDocument) { | |
1556 CloseParser(); | 1553 CloseParser(); |
1557 m_bXRefStream = FALSE; | 1554 m_bXRefStream = FALSE; |
1558 m_LastXRefOffset = 0; | 1555 m_LastXRefOffset = 0; |
1559 m_bOwnFileRead = true; | 1556 m_bOwnFileRead = true; |
1560 | 1557 |
1561 int32_t offset = GetHeaderOffset(pFileAccess); | 1558 int32_t offset = GetHeaderOffset(pFileAccess); |
1562 if (offset == -1) | 1559 if (offset == -1) |
1563 return FORMAT_ERROR; | 1560 return FORMAT_ERROR; |
1564 | 1561 |
1565 if (!IsLinearizedFile(pFileAccess, offset)) { | 1562 if (!IsLinearizedFile(pFileAccess, offset)) { |
1566 m_pSyntax->m_pFileAccess = nullptr; | 1563 m_pSyntax->m_pFileAccess = nullptr; |
1567 return StartParse(pFileAccess, std::move(pDocument)); | 1564 return StartParse(pFileAccess, std::move(pDocument)); |
1568 } | 1565 } |
1569 | 1566 |
1570 m_pDocument = std::move(pDocument); | 1567 m_pDocument = pDocument; |
1571 FX_FILESIZE dwFirstXRefOffset = m_pSyntax->SavePos(); | 1568 FX_FILESIZE dwFirstXRefOffset = m_pSyntax->SavePos(); |
1572 | 1569 |
1573 FX_BOOL bXRefRebuilt = FALSE; | 1570 FX_BOOL bXRefRebuilt = FALSE; |
1574 FX_BOOL bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE); | 1571 FX_BOOL bLoadV4 = LoadCrossRefV4(dwFirstXRefOffset, 0, FALSE); |
1575 if (!bLoadV4 && !LoadCrossRefV5(&dwFirstXRefOffset, TRUE)) { | 1572 if (!bLoadV4 && !LoadCrossRefV5(&dwFirstXRefOffset, TRUE)) { |
1576 if (!RebuildCrossRef()) | 1573 if (!RebuildCrossRef()) |
1577 return FORMAT_ERROR; | 1574 return FORMAT_ERROR; |
1578 | 1575 |
1579 bXRefRebuilt = TRUE; | 1576 bXRefRebuilt = TRUE; |
1580 m_LastXRefOffset = 0; | 1577 m_LastXRefOffset = 0; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1676 if (!LoadLinearizedAllCrossRefV4(m_LastXRefOffset, m_dwXrefStartObjNum) && | 1673 if (!LoadLinearizedAllCrossRefV4(m_LastXRefOffset, m_dwXrefStartObjNum) && |
1677 !LoadLinearizedAllCrossRefV5(m_LastXRefOffset)) { | 1674 !LoadLinearizedAllCrossRefV5(m_LastXRefOffset)) { |
1678 m_LastXRefOffset = 0; | 1675 m_LastXRefOffset = 0; |
1679 m_pSyntax->m_MetadataObjnum = dwSaveMetadataObjnum; | 1676 m_pSyntax->m_MetadataObjnum = dwSaveMetadataObjnum; |
1680 return FORMAT_ERROR; | 1677 return FORMAT_ERROR; |
1681 } | 1678 } |
1682 | 1679 |
1683 m_pSyntax->m_MetadataObjnum = dwSaveMetadataObjnum; | 1680 m_pSyntax->m_MetadataObjnum = dwSaveMetadataObjnum; |
1684 return SUCCESS; | 1681 return SUCCESS; |
1685 } | 1682 } |
OLD | NEW |