diff options
-rw-r--r-- | core/fpdfapi/parser/cpdf_hint_tables.cpp | 82 | ||||
-rw-r--r-- | core/fpdfapi/parser/cpdf_hint_tables.h | 11 | ||||
-rw-r--r-- | core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp | 25 |
3 files changed, 58 insertions, 60 deletions
diff --git a/core/fpdfapi/parser/cpdf_hint_tables.cpp b/core/fpdfapi/parser/cpdf_hint_tables.cpp index fc9a46d68a..f4f87d59e6 100644 --- a/core/fpdfapi/parser/cpdf_hint_tables.cpp +++ b/core/fpdfapi/parser/cpdf_hint_tables.cpp @@ -277,60 +277,38 @@ bool CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream, return false; } - const uint32_t nFirstPageObjNum = m_pLinearized->GetFirstPageObjNum(); - - uint32_t dwPrevObjLen = 0; - uint32_t dwCurObjLen = 0; FX_SAFE_UINT32 required_bits = dwSharedObjTotal; required_bits *= dwDeltaGroupLen; if (!CanReadFromBitStream(hStream, required_bits)) return false; - for (uint32_t i = 0; i < dwSharedObjTotal; ++i) { - dwPrevObjLen = dwCurObjLen; - FX_SAFE_UINT32 safeObjLen = hStream->GetBits(dwDeltaGroupLen); - safeObjLen += dwGroupLeastLen; - if (!safeObjLen.IsValid()) - return false; - - dwCurObjLen = safeObjLen.ValueOrDie(); - if (i < m_nFirstPageSharedObjs) { - m_dwSharedObjNumArray.push_back(nFirstPageObjNum + i); - if (i == 0) - m_szSharedObjOffsetArray.push_back(m_szFirstPageObjOffset); - } else { + if (dwSharedObjTotal > 0) { + uint32_t dwLastSharedObj = dwSharedObjTotal - 1; + if (dwLastSharedObj > m_nFirstPageSharedObjs) { FX_SAFE_UINT32 safeObjNum = dwFirstSharedObjNum; - safeObjNum += i - m_nFirstPageSharedObjs; + safeObjNum += dwLastSharedObj - m_nFirstPageSharedObjs; if (!safeObjNum.IsValid()) return false; - - m_dwSharedObjNumArray.push_back(safeObjNum.ValueOrDie()); - if (i == m_nFirstPageSharedObjs) { - FX_SAFE_FILESIZE safeLoc = szFirstSharedObjLoc; - if (!safeLoc.IsValid()) - return false; - - m_szSharedObjOffsetArray.push_back(safeLoc.ValueOrDie()); - } - } - - if (i != 0 && i != m_nFirstPageSharedObjs) { - FX_SAFE_FILESIZE safeLoc = dwPrevObjLen; - safeLoc += m_szSharedObjOffsetArray[i - 1]; - if (!safeLoc.IsValid()) - return false; - - m_szSharedObjOffsetArray.push_back(safeLoc.ValueOrDie()); } } - if (dwSharedObjTotal > 0) { - FX_SAFE_FILESIZE safeLoc = dwCurObjLen; - safeLoc += m_szSharedObjOffsetArray[dwSharedObjTotal - 1]; - if (!safeLoc.IsValid()) + m_SharedObjGroupInfos.resize(dwSharedObjTotal); + FX_SAFE_FILESIZE prev_shared_group_end_offset = m_szFirstPageObjOffset; + for (uint32_t i = 0; i < dwSharedObjTotal; ++i) { + if (i == m_nFirstPageSharedObjs) + prev_shared_group_end_offset = szFirstSharedObjLoc; + + FX_SAFE_UINT32 safeObjLen = hStream->GetBits(dwDeltaGroupLen); + safeObjLen += dwGroupLeastLen; + if (!safeObjLen.IsValid()) return false; - m_szSharedObjOffsetArray.push_back(safeLoc.ValueOrDie()); + m_SharedObjGroupInfos[i].m_dwLength = safeObjLen.ValueOrDie(); + m_SharedObjGroupInfos[i].m_szOffset = + prev_shared_group_end_offset.ValueOrDie(); + prev_shared_group_end_offset += m_SharedObjGroupInfos[i].m_dwLength; + if (!prev_shared_group_end_offset.IsValid()) + return false; } hStream->ByteAlign(); @@ -362,7 +340,7 @@ CPDF_DataAvail::DocAvailStatus CPDF_HintTables::CheckPage(uint32_t index) { if (index >= m_pLinearized->GetPageCount()) return CPDF_DataAvail::DataError; - uint32_t dwLength = m_PageInfos[index].page_length(); + const uint32_t dwLength = m_PageInfos[index].page_length(); if (!dwLength) return CPDF_DataAvail::DataError; @@ -372,27 +350,17 @@ CPDF_DataAvail::DocAvailStatus CPDF_HintTables::CheckPage(uint32_t index) { } // Download data of shared objects in the page. - const uint32_t nFirstPageObjNum = m_pLinearized->GetFirstPageObjNum(); - - uint32_t dwObjNum = 0; for (const uint32_t dwIndex : m_PageInfos[index].Identifiers()) { - if (dwIndex >= m_dwSharedObjNumArray.size()) + if (dwIndex >= m_SharedObjGroupInfos.size()) continue; + const SharedObjGroupInfo& shared_group_info = + m_SharedObjGroupInfos[dwIndex]; - dwObjNum = m_dwSharedObjNumArray[dwIndex]; - if (dwObjNum >= static_cast<uint32_t>(nFirstPageObjNum) && - dwObjNum < - static_cast<uint32_t>(nFirstPageObjNum) + m_nFirstPageSharedObjs) { - continue; - } - - dwLength = GetItemLength(dwIndex, m_szSharedObjOffsetArray); - // If two objects have the same offset, it should be treated as an error. - if (!dwLength) + if (!shared_group_info.m_szOffset || !shared_group_info.m_dwLength) return CPDF_DataAvail::DataError; if (!m_pValidator->CheckDataRangeAndRequestIfUnavailable( - m_szSharedObjOffsetArray[dwIndex], dwLength)) { + shared_group_info.m_szOffset, shared_group_info.m_dwLength)) { return CPDF_DataAvail::DataNotAvailable; } } diff --git a/core/fpdfapi/parser/cpdf_hint_tables.h b/core/fpdfapi/parser/cpdf_hint_tables.h index 0db190b189..861f231547 100644 --- a/core/fpdfapi/parser/cpdf_hint_tables.h +++ b/core/fpdfapi/parser/cpdf_hint_tables.h @@ -20,6 +20,11 @@ class CPDF_ReadValidator; class CPDF_HintTables { public: + struct SharedObjGroupInfo { + FX_FILESIZE m_szOffset = 0; + uint32_t m_dwLength = 0; + }; + class PageInfo { public: PageInfo(); @@ -74,6 +79,9 @@ class CPDF_HintTables { bool LoadHintStream(CPDF_Stream* pHintStream); const std::vector<PageInfo>& PageInfos() const { return m_PageInfos; } + const std::vector<SharedObjGroupInfo>& SharedGroupInfos() const { + return m_SharedObjGroupInfos; + } protected: bool ReadPageHintTable(CFX_BitStream* hStream); @@ -95,8 +103,7 @@ class CPDF_HintTables { FX_FILESIZE m_szFirstPageObjOffset; std::vector<PageInfo> m_PageInfos; - std::vector<uint32_t> m_dwSharedObjNumArray; - std::vector<FX_FILESIZE> m_szSharedObjOffsetArray; + std::vector<SharedObjGroupInfo> m_SharedObjGroupInfos; }; #endif // CORE_FPDFAPI_PARSER_CPDF_HINT_TABLES_H_ diff --git a/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp b/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp index 3d98196093..af0e9ff745 100644 --- a/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp +++ b/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp @@ -10,6 +10,8 @@ #include "core/fpdfapi/cpdf_modulemgr.h" #include "core/fpdfapi/parser/cpdf_data_avail.h" +#include "core/fpdfapi/parser/cpdf_object.h" +#include "core/fpdfapi/parser/cpdf_syntax_parser.h" #include "core/fxcrt/fx_stream.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -68,7 +70,7 @@ TEST_F(CPDF_HintTablesTest, Load) { hint_tables->GetPagePos(2, &page_start, &page_length, &page_obj_num)); } -TEST_F(CPDF_HintTablesTest, PageInfos) { +TEST_F(CPDF_HintTablesTest, PageAndGroupInfos) { auto data_avail = MakeDataAvailFromFile("feature_linearized_loading.pdf"); ASSERT_EQ(CPDF_DataAvail::DocAvailStatus::DataAvailable, data_avail->IsDocAvail(nullptr)); @@ -95,4 +97,25 @@ TEST_F(CPDF_HintTablesTest, PageInfos) { EXPECT_EQ(2u, hint_tables->PageInfos()[1].Identifiers()[0]); EXPECT_EQ(5u, hint_tables->PageInfos()[1].Identifiers()[1]); EXPECT_EQ(3u, hint_tables->PageInfos()[1].Identifiers()[2]); + + // SharedGroupInfo + ASSERT_EQ(6u, hint_tables->SharedGroupInfos().size()); + + EXPECT_EQ(777, hint_tables->SharedGroupInfos()[0].m_szOffset); + EXPECT_EQ(254u, hint_tables->SharedGroupInfos()[0].m_dwLength); + + EXPECT_EQ(1031, hint_tables->SharedGroupInfos()[1].m_szOffset); + EXPECT_EQ(389u, hint_tables->SharedGroupInfos()[1].m_dwLength); + + EXPECT_EQ(1420, hint_tables->SharedGroupInfos()[2].m_szOffset); + EXPECT_EQ(726u, hint_tables->SharedGroupInfos()[2].m_dwLength); + + EXPECT_EQ(2146, hint_tables->SharedGroupInfos()[3].m_szOffset); + EXPECT_EQ(290u, hint_tables->SharedGroupInfos()[3].m_dwLength); + + EXPECT_EQ(2436, hint_tables->SharedGroupInfos()[4].m_szOffset); + EXPECT_EQ(2669u, hint_tables->SharedGroupInfos()[4].m_dwLength); + + EXPECT_EQ(10939, hint_tables->SharedGroupInfos()[5].m_szOffset); + EXPECT_EQ(544u, hint_tables->SharedGroupInfos()[5].m_dwLength); } |