diff options
Diffstat (limited to 'core/fpdfapi')
-rw-r--r-- | core/fpdfapi/edit/cpdf_creator.cpp | 8 | ||||
-rw-r--r-- | core/fpdfapi/parser/cpdf_data_avail.cpp | 7 | ||||
-rw-r--r-- | core/fpdfapi/parser/cpdf_parser.cpp | 79 | ||||
-rw-r--r-- | core/fpdfapi/parser/cpdf_parser.h | 13 | ||||
-rw-r--r-- | core/fpdfapi/parser/cpdf_parser_unittest.cpp | 47 |
5 files changed, 114 insertions, 40 deletions
diff --git a/core/fpdfapi/edit/cpdf_creator.cpp b/core/fpdfapi/edit/cpdf_creator.cpp index 858d56cbaf..ceffa5077f 100644 --- a/core/fpdfapi/edit/cpdf_creator.cpp +++ b/core/fpdfapi/edit/cpdf_creator.cpp @@ -323,9 +323,9 @@ bool CPDF_Creator::WriteOldIndirectObject(uint32_t objnum) { m_ObjectOffsets[objnum] = m_Archive->CurrentOffset(); bool bExistInMap = !!m_pDocument->GetIndirectObject(objnum); - const uint8_t object_type = m_pParser->GetObjectType(objnum); + const CPDF_Parser::ObjectType object_type = m_pParser->GetObjectType(objnum); if (m_pParser->IsVersionUpdated() || m_bSecurityChanged || bExistInMap || - (object_type == 2 && m_pEncryptDict)) { + (object_type == CPDF_Parser::ObjectType::kCompressed && m_pEncryptDict)) { CPDF_Object* pObj = m_pDocument->GetOrParseIndirectObject(objnum); if (!pObj) { m_ObjectOffsets.erase(objnum); @@ -341,7 +341,7 @@ bool CPDF_Creator::WriteOldIndirectObject(uint32_t objnum) { m_pParser->GetIndirectBinary(objnum, pBuffer, size); if (!pBuffer) return true; - if (object_type == 2) { + if (object_type == CPDF_Parser::ObjectType::kCompressed) { if (!m_Archive->WriteDWord(objnum) || !m_Archive->WriteString(" 0 obj ") || !m_Archive->WriteBlock(pBuffer, size) || @@ -412,7 +412,7 @@ void CPDF_Creator::InitNewObjNumOffsets() { continue; } if (m_pParser && m_pParser->IsValidObjectNumber(objnum) && - m_pParser->GetObjectType(objnum)) { + m_pParser->GetObjectType(objnum) != CPDF_Parser::ObjectType::kFree) { continue; } m_NewObjNumArray.insert(std::lower_bound(m_NewObjNumArray.begin(), diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp index b4da893429..6f12260eae 100644 --- a/core/fpdfapi/parser/cpdf_data_avail.cpp +++ b/core/fpdfapi/parser/cpdf_data_avail.cpp @@ -94,11 +94,12 @@ uint32_t CPDF_DataAvail::GetObjectSize(uint32_t objnum, FX_FILESIZE& offset) { if (!pParser || !pParser->IsValidObjectNumber(objnum)) return 0; - if (pParser->GetObjectType(objnum) == 2) + if (pParser->GetObjectType(objnum) == CPDF_Parser::ObjectType::kCompressed) objnum = pParser->GetObjectPositionOrZero(objnum); - if (pParser->GetObjectType(objnum) != 1 && - pParser->GetObjectType(objnum) != 255) { + if (pParser->GetObjectType(objnum) != + CPDF_Parser::ObjectType::kNotCompressed && + pParser->GetObjectType(objnum) != CPDF_Parser::ObjectType::kNull) { return 0; } diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp index 841bf2778a..0f4da6e28f 100644 --- a/core/fpdfapi/parser/cpdf_parser.cpp +++ b/core/fpdfapi/parser/cpdf_parser.cpp @@ -49,6 +49,20 @@ int32_t GetStreamFirst(const CFX_RetainPtr<CPDF_StreamAcc>& pObjStream) { return pObjStream->GetDict()->GetIntegerFor("First"); } +CPDF_Parser::ObjectType GetObjectTypeFromCrossRefStreamType( + int cross_ref_stream_type) { + switch (cross_ref_stream_type) { + case 0: + return CPDF_Parser::ObjectType::kFree; + case 1: + return CPDF_Parser::ObjectType::kNotCompressed; + case 2: + return CPDF_Parser::ObjectType::kCompressed; + default: + return CPDF_Parser::ObjectType::kNull; + } +} + } // namespace CPDF_Parser::CPDF_Parser() @@ -78,10 +92,10 @@ FX_FILESIZE CPDF_Parser::GetObjectPositionOrZero(uint32_t objnum) const { return it != m_ObjectInfo.end() ? it->second.pos : 0; } -uint8_t CPDF_Parser::GetObjectType(uint32_t objnum) const { +CPDF_Parser::ObjectType CPDF_Parser::GetObjectType(uint32_t objnum) const { ASSERT(IsValidObjectNumber(objnum)); auto it = m_ObjectInfo.find(objnum); - return it != m_ObjectInfo.end() ? it->second.type : 0; + return it != m_ObjectInfo.end() ? it->second.type : ObjectType::kFree; } uint16_t CPDF_Parser::GetObjectGenNum(uint32_t objnum) const { @@ -91,8 +105,16 @@ uint16_t CPDF_Parser::GetObjectGenNum(uint32_t objnum) const { } bool CPDF_Parser::IsObjectFreeOrNull(uint32_t objnum) const { - uint8_t type = GetObjectType(objnum); - return type == 0 || type == 255; + switch (GetObjectType(objnum)) { + case ObjectType::kFree: + case ObjectType::kNull: + return true; + case ObjectType::kNotCompressed: + case ObjectType::kCompressed: + return false; + } + ASSERT(false); // NOTREACHED(); + return false; } void CPDF_Parser::SetEncryptDictionary(CPDF_Dictionary* pDict) { @@ -265,10 +287,10 @@ FX_FILESIZE CPDF_Parser::GetObjectOffset(uint32_t objnum) const { if (!IsValidObjectNumber(objnum)) return 0; - if (GetObjectType(objnum) == 1) + if (GetObjectType(objnum) == ObjectType::kNotCompressed) return GetObjectPositionOrZero(objnum); - if (GetObjectType(objnum) == 2) { + if (GetObjectType(objnum) == ObjectType::kCompressed) { FX_FILESIZE pos = GetObjectPositionOrZero(objnum); return GetObjectPositionOrZero(pos); } @@ -444,7 +466,7 @@ bool CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, char* pEntry = &buf[i * recordsize]; if (pEntry[17] == 'f') { m_ObjectInfo[objnum].pos = 0; - m_ObjectInfo[objnum].type = 0; + m_ObjectInfo[objnum].type = ObjectType::kFree; } else { int32_t offset = FXSYS_atoi(pEntry); if (offset == 0) { @@ -463,7 +485,7 @@ bool CPDF_Parser::LoadLinearizedCrossRefV4(FX_FILESIZE pos, if (m_ObjectInfo[objnum].pos < m_pSyntax->m_FileLen) m_SortedOffset.insert(m_ObjectInfo[objnum].pos); - m_ObjectInfo[objnum].type = 1; + m_ObjectInfo[objnum].type = ObjectType::kNotCompressed; } } } @@ -519,7 +541,7 @@ bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, char* pEntry = &buf[i * recordsize]; if (pEntry[17] == 'f') { m_ObjectInfo[objnum].pos = 0; - m_ObjectInfo[objnum].type = 0; + m_ObjectInfo[objnum].type = ObjectType::kFree; } else { FX_FILESIZE offset = (FX_FILESIZE)FXSYS_atoi64(pEntry); if (offset == 0) { @@ -538,7 +560,7 @@ bool CPDF_Parser::LoadCrossRefV4(FX_FILESIZE pos, if (m_ObjectInfo[objnum].pos < m_pSyntax->m_FileLen) m_SortedOffset.insert(m_ObjectInfo[objnum].pos); - m_ObjectInfo[objnum].type = 1; + m_ObjectInfo[objnum].type = ObjectType::kNotCompressed; } } } @@ -766,7 +788,7 @@ bool CPDF_Parser::RebuildCrossRef() { } } else { m_ObjectInfo[objnum].pos = obj_pos; - m_ObjectInfo[objnum].type = 1; + m_ObjectInfo[objnum].type = ObjectType::kNotCompressed; m_ObjectInfo[objnum].gennum = gennum; } } @@ -959,7 +981,7 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) { m_TrailerPos = m_Trailers.size() - 1; ShrinkObjectMap(size); for (auto& it : m_ObjectInfo) - it.second.type = 0; + it.second.type = ObjectType::kFree; } else { m_Trailers.push_back(std::move(pNewTrailer)); } @@ -1027,12 +1049,15 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) { continue; for (uint32_t j = 0; j < count; j++) { - int32_t type = 1; + ObjectType type = ObjectType::kNotCompressed; const uint8_t* entrystart = segstart + j * totalWidth; - if (WidthArray[0]) - type = GetVarInt(entrystart, WidthArray[0]); + if (WidthArray[0]) { + const int cross_ref_stream_obj_type = + GetVarInt(entrystart, WidthArray[0]); + type = GetObjectTypeFromCrossRefStreamType(cross_ref_stream_obj_type); + } - if (GetObjectType(startnum + j) == 255) { + if (GetObjectType(startnum + j) == ObjectType::kNull) { FX_FILESIZE offset = GetVarInt(entrystart + WidthArray[0], WidthArray[1]); m_ObjectInfo[startnum + j].pos = offset; @@ -1040,22 +1065,22 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) { continue; } - if (GetObjectType(startnum + j)) + if (GetObjectType(startnum + j) != ObjectType::kFree) continue; m_ObjectInfo[startnum + j].type = type; - if (type == 0) { + if (type == ObjectType::kFree) { m_ObjectInfo[startnum + j].pos = 0; } else { FX_FILESIZE offset = GetVarInt(entrystart + WidthArray[0], WidthArray[1]); m_ObjectInfo[startnum + j].pos = offset; - if (type == 1) { + if (type == ObjectType::kNotCompressed) { m_SortedOffset.insert(offset); } else { if (offset < 0 || !IsValidObjectNumber(offset)) return false; - m_ObjectInfo[offset].type = 255; + m_ObjectInfo[offset].type = ObjectType::kNull; } } } @@ -1117,13 +1142,14 @@ std::unique_ptr<CPDF_Object> CPDF_Parser::ParseIndirectObject( return nullptr; pdfium::ScopedSetInsertion<uint32_t> local_insert(&m_ParsingObjNums, objnum); - if (GetObjectType(objnum) == 1 || GetObjectType(objnum) == 255) { + if (GetObjectType(objnum) == ObjectType::kNotCompressed || + GetObjectType(objnum) == ObjectType::kNull) { FX_FILESIZE pos = m_ObjectInfo[objnum].pos; if (pos <= 0) return nullptr; return ParseIndirectObjectAt(pObjList, pos, objnum); } - if (GetObjectType(objnum) != 2) + if (GetObjectType(objnum) != ObjectType::kCompressed) return nullptr; CFX_RetainPtr<CPDF_StreamAcc> pObjStream = @@ -1178,10 +1204,11 @@ FX_FILESIZE CPDF_Parser::GetObjectSize(uint32_t objnum) const { if (!IsValidObjectNumber(objnum)) return 0; - if (GetObjectType(objnum) == 2) + if (GetObjectType(objnum) == ObjectType::kCompressed) objnum = GetObjectPositionOrZero(objnum); - if (GetObjectType(objnum) != 1 && GetObjectType(objnum) != 255) + if (GetObjectType(objnum) != ObjectType::kNotCompressed && + GetObjectType(objnum) != ObjectType::kNull) return 0; FX_FILESIZE offset = GetObjectPositionOrZero(objnum); @@ -1203,7 +1230,7 @@ void CPDF_Parser::GetIndirectBinary(uint32_t objnum, if (!IsValidObjectNumber(objnum)) return; - if (GetObjectType(objnum) == 2) { + if (GetObjectType(objnum) == ObjectType::kCompressed) { CFX_RetainPtr<CPDF_StreamAcc> pObjStream = GetObjectStream(m_ObjectInfo[objnum].pos); if (!pObjStream) @@ -1238,7 +1265,7 @@ void CPDF_Parser::GetIndirectBinary(uint32_t objnum, return; } - if (GetObjectType(objnum) != 1) + if (GetObjectType(objnum) != ObjectType::kNotCompressed) return; FX_FILESIZE pos = m_ObjectInfo[objnum].pos; diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h index efe10555f7..3acdbbfa6f 100644 --- a/core/fpdfapi/parser/cpdf_parser.h +++ b/core/fpdfapi/parser/cpdf_parser.h @@ -38,6 +38,13 @@ class CPDF_Parser { HANDLER_ERROR }; + enum class ObjectType : uint8_t { + kFree = 0x00, + kNotCompressed = 0x01, + kCompressed = 0x02, + kNull = 0xFF, + }; + // A limit on the maximum object number in the xref table. Theoretical limits // are higher, but this may be large enough in practice. static const uint32_t kMaxObjectNumber = 1048576; @@ -74,7 +81,7 @@ class CPDF_Parser { uint32_t GetLastObjNum() const; bool IsValidObjectNumber(uint32_t objnum) const; FX_FILESIZE GetObjectPositionOrZero(uint32_t objnum) const; - uint8_t GetObjectType(uint32_t objnum) const; + ObjectType GetObjectType(uint32_t objnum) const; uint16_t GetObjectGenNum(uint32_t objnum) const; bool IsVersionUpdated() const { return m_bVersionUpdated; } bool IsObjectFreeOrNull(uint32_t objnum) const; @@ -103,10 +110,10 @@ class CPDF_Parser { protected: struct ObjectInfo { - ObjectInfo() : pos(0), type(0), gennum(0) {} + ObjectInfo() : pos(0), type(ObjectType::kFree), gennum(0) {} FX_FILESIZE pos; - uint8_t type; + ObjectType type; uint16_t gennum; }; diff --git a/core/fpdfapi/parser/cpdf_parser_unittest.cpp b/core/fpdfapi/parser/cpdf_parser_unittest.cpp index f988f8248b..25c22c701b 100644 --- a/core/fpdfapi/parser/cpdf_parser_unittest.cpp +++ b/core/fpdfapi/parser/cpdf_parser_unittest.cpp @@ -118,7 +118,13 @@ TEST(cpdf_parser, LoadCrossRefV4) { ASSERT_TRUE(parser.LoadCrossRefV4(0, 0, false)); const FX_FILESIZE offsets[] = {0, 17, 81, 0, 331, 409}; - const uint8_t types[] = {0, 1, 1, 0, 1, 1}; + const CPDF_Parser::ObjectType types[] = { + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kNotCompressed, + CPDF_Parser::ObjectType::kNotCompressed, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kNotCompressed, + CPDF_Parser::ObjectType::kNotCompressed}; for (size_t i = 0; i < FX_ArraySize(offsets); ++i) { EXPECT_EQ(offsets[i], parser.m_ObjectInfo[i].pos); EXPECT_EQ(types[i], parser.m_ObjectInfo[i].type); @@ -144,7 +150,20 @@ TEST(cpdf_parser, LoadCrossRefV4) { ASSERT_TRUE(parser.LoadCrossRefV4(0, 0, false)); const FX_FILESIZE offsets[] = {0, 0, 0, 25325, 0, 0, 0, 0, 25518, 25635, 0, 0, 25777}; - const uint8_t types[] = {0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1}; + const CPDF_Parser::ObjectType types[] = { + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kNotCompressed, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kNotCompressed, + CPDF_Parser::ObjectType::kNotCompressed, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kNotCompressed}; for (size_t i = 0; i < FX_ArraySize(offsets); ++i) { EXPECT_EQ(offsets[i], parser.m_ObjectInfo[i].pos); EXPECT_EQ(types[i], parser.m_ObjectInfo[i].type); @@ -170,7 +189,20 @@ TEST(cpdf_parser, LoadCrossRefV4) { ASSERT_TRUE(parser.LoadCrossRefV4(0, 0, false)); const FX_FILESIZE offsets[] = {0, 0, 0, 25325, 0, 0, 0, 0, 0, 25635, 0, 0, 25777}; - const uint8_t types[] = {0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1}; + const CPDF_Parser::ObjectType types[] = { + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kNotCompressed, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kNotCompressed, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kNotCompressed}; for (size_t i = 0; i < FX_ArraySize(offsets); ++i) { EXPECT_EQ(offsets[i], parser.m_ObjectInfo[i].pos); EXPECT_EQ(types[i], parser.m_ObjectInfo[i].type); @@ -194,7 +226,14 @@ TEST(cpdf_parser, LoadCrossRefV4) { ASSERT_TRUE(parser.LoadCrossRefV4(0, 0, false)); const FX_FILESIZE offsets[] = {0, 23, 0, 0, 0, 45, 179}; - const uint8_t types[] = {0, 1, 0, 0, 0, 1, 1}; + const CPDF_Parser::ObjectType types[] = { + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kNotCompressed, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kFree, + CPDF_Parser::ObjectType::kNotCompressed, + CPDF_Parser::ObjectType::kNotCompressed}; for (size_t i = 0; i < FX_ArraySize(offsets); ++i) { EXPECT_EQ(offsets[i], parser.m_ObjectInfo[i].pos); EXPECT_EQ(types[i], parser.m_ObjectInfo[i].type); |