diff options
-rw-r--r-- | core/fpdfapi/parser/cpdf_hint_tables.cpp | 53 | ||||
-rw-r--r-- | core/fpdfapi/parser/cpdf_hint_tables.h | 8 | ||||
-rw-r--r-- | core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp | 12 |
3 files changed, 65 insertions, 8 deletions
diff --git a/core/fpdfapi/parser/cpdf_hint_tables.cpp b/core/fpdfapi/parser/cpdf_hint_tables.cpp index 04e673bc97..8d8aa3263a 100644 --- a/core/fpdfapi/parser/cpdf_hint_tables.cpp +++ b/core/fpdfapi/parser/cpdf_hint_tables.cpp @@ -233,6 +233,8 @@ bool CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream, // Item 1: The object number of the first object in the shared objects // section. uint32_t dwFirstSharedObjNum = hStream->GetBits(32); + if (!dwFirstSharedObjNum) + return false; // Item 2: The location of the first object in the shared objects section. const FX_FILESIZE szFirstSharedObjLoc = @@ -248,8 +250,8 @@ bool CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream, uint32_t dwSharedObjTotal = hStream->GetBits(32); // Item 5: The number of bits needed to represent the greatest number of - // objects in a shared object group. Skipped. - hStream->SkipBits(16); + // objects in a shared object group. + uint32_t dwSharedObjNumBits = hStream->GetBits(16); // Item 6: The least length of a shared object group in bytes. uint32_t dwGroupLeastLen = hStream->GetBits(32); @@ -285,6 +287,9 @@ bool CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream, } m_SharedObjGroupInfos.resize(dwSharedObjTotal); + // Table F.6 – Shared object hint table, shared object group entries: + // Item 1: A number that, when added to the least shared object + // group length. FX_SAFE_FILESIZE prev_shared_group_end_offset = m_szFirstPageObjOffset; for (uint32_t i = 0; i < dwSharedObjTotal; ++i) { if (i == m_nFirstPageSharedObjs) @@ -304,10 +309,48 @@ bool CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream, } hStream->ByteAlign(); - if (hStream->BitsRemaining() < dwSharedObjTotal) - return false; + { + // Item 2: A flag indicating whether the shared object signature (item 3) is + // present. + uint32_t signature_count = 0; + for (uint32_t i = 0; i < dwSharedObjTotal; ++i) { + signature_count += hStream->GetBits(1); + } + hStream->ByteAlign(); + // Item 3: (Only if item 2 is 1) The shared object signature, a 16-byte MD5 + // hash that uniquely identifies the resource that the group of objects + // represents. + if (signature_count) { + required_bits = signature_count; + required_bits *= 128; + if (!CanReadFromBitStream(hStream, required_bits)) + return false; + + hStream->SkipBits(required_bits.ValueOrDie()); + hStream->ByteAlign(); + } + } + // Item 4: A number equal to 1 less than the number of objects in the group. + FX_SAFE_UINT32 cur_obj_num = m_pLinearized->GetFirstPageObjNum(); + for (uint32_t i = 0; i < dwSharedObjTotal; ++i) { + if (i == m_nFirstPageSharedObjs) + cur_obj_num = dwFirstSharedObjNum; + + FX_SAFE_UINT32 obj_count = + dwSharedObjNumBits ? hStream->GetBits(dwSharedObjNumBits) : 0; + obj_count += 1; + if (!obj_count.IsValid()) + return false; + + uint32_t obj_num = cur_obj_num.ValueOrDie(); + cur_obj_num += obj_count.ValueOrDie(); + if (!cur_obj_num.IsValid()) + return false; + + m_SharedObjGroupInfos[i].m_dwStartObjNum = obj_num; + m_SharedObjGroupInfos[i].m_dwObjectsCount = obj_count.ValueOrDie(); + } - hStream->SkipBits(dwSharedObjTotal); hStream->ByteAlign(); return true; } diff --git a/core/fpdfapi/parser/cpdf_hint_tables.h b/core/fpdfapi/parser/cpdf_hint_tables.h index 5b978f99b2..20ba9be051 100644 --- a/core/fpdfapi/parser/cpdf_hint_tables.h +++ b/core/fpdfapi/parser/cpdf_hint_tables.h @@ -23,6 +23,8 @@ class CPDF_HintTables { struct SharedObjGroupInfo { FX_FILESIZE m_szOffset = 0; uint32_t m_dwLength = 0; + uint32_t m_dwObjectsCount = 0; + uint32_t m_dwStartObjNum = 0; }; class PageInfo { @@ -31,9 +33,9 @@ class CPDF_HintTables { ~PageInfo(); void set_objects_count(uint32_t objects_count) { - m_nObjectsCount = objects_count; + m_dwObjectsCount = objects_count; } - uint32_t objects_count() const { return m_nObjectsCount; } + uint32_t objects_count() const { return m_dwObjectsCount; } void set_page_offset(FX_FILESIZE offset) { m_szOffset = offset; } FX_FILESIZE page_offset() const { return m_szOffset; } @@ -55,7 +57,7 @@ class CPDF_HintTables { } private: - uint32_t m_nObjectsCount = 0; + uint32_t m_dwObjectsCount = 0; FX_FILESIZE m_szOffset = 0; uint32_t m_dwLength = 0; uint32_t m_dwStartObjNum = 0; diff --git a/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp b/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp index dba39f5594..97ba434768 100644 --- a/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp +++ b/core/fpdfapi/parser/cpdf_hint_tables_unittest.cpp @@ -130,21 +130,33 @@ TEST_F(CPDF_HintTablesTest, PageAndGroupInfos) { EXPECT_EQ(777, hint_tables->SharedGroupInfos()[0].m_szOffset); EXPECT_EQ(254u, hint_tables->SharedGroupInfos()[0].m_dwLength); + EXPECT_EQ(39u, hint_tables->SharedGroupInfos()[0].m_dwStartObjNum); + EXPECT_EQ(1u, hint_tables->SharedGroupInfos()[0].m_dwObjectsCount); EXPECT_EQ(1031, hint_tables->SharedGroupInfos()[1].m_szOffset); EXPECT_EQ(389u, hint_tables->SharedGroupInfos()[1].m_dwLength); + EXPECT_EQ(40u, hint_tables->SharedGroupInfos()[1].m_dwStartObjNum); + EXPECT_EQ(1u, hint_tables->SharedGroupInfos()[1].m_dwObjectsCount); EXPECT_EQ(1420, hint_tables->SharedGroupInfos()[2].m_szOffset); EXPECT_EQ(726u, hint_tables->SharedGroupInfos()[2].m_dwLength); + EXPECT_EQ(41u, hint_tables->SharedGroupInfos()[2].m_dwStartObjNum); + EXPECT_EQ(1u, hint_tables->SharedGroupInfos()[2].m_dwObjectsCount); EXPECT_EQ(2146, hint_tables->SharedGroupInfos()[3].m_szOffset); EXPECT_EQ(290u, hint_tables->SharedGroupInfos()[3].m_dwLength); + EXPECT_EQ(42u, hint_tables->SharedGroupInfos()[3].m_dwStartObjNum); + EXPECT_EQ(1u, hint_tables->SharedGroupInfos()[3].m_dwObjectsCount); EXPECT_EQ(2436, hint_tables->SharedGroupInfos()[4].m_szOffset); EXPECT_EQ(2669u, hint_tables->SharedGroupInfos()[4].m_dwLength); + EXPECT_EQ(43u, hint_tables->SharedGroupInfos()[4].m_dwStartObjNum); + EXPECT_EQ(1u, hint_tables->SharedGroupInfos()[4].m_dwObjectsCount); EXPECT_EQ(10939, hint_tables->SharedGroupInfos()[5].m_szOffset); EXPECT_EQ(544u, hint_tables->SharedGroupInfos()[5].m_dwLength); + EXPECT_EQ(4u, hint_tables->SharedGroupInfos()[5].m_dwStartObjNum); + EXPECT_EQ(1u, hint_tables->SharedGroupInfos()[5].m_dwObjectsCount); } TEST_F(CPDF_HintTablesTest, FirstPageOffset) { |