Remove CPDF_CrossRefTable::ObjectType::kObjStream There's really no such type. There is, however, a normal object which we've flagged as being an object stream. Make this an attribute of all types of ObjectInfo to steal byte otherwise used as padding. Change-Id: I5caa5e2c3b3890c7c571a38b7de32fbf63f4da69 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/114770 Commit-Queue: Tom Sepez <tsepez@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_table.cpp b/core/fpdfapi/parser/cpdf_cross_ref_table.cpp index 0d9c14f..c0dc754 100644 --- a/core/fpdfapi/parser/cpdf_cross_ref_table.cpp +++ b/core/fpdfapi/parser/cpdf_cross_ref_table.cpp
@@ -44,19 +44,22 @@ if (info.gennum > 0) return; - if (info.type == ObjectType::kObjStream) + // Don't add known object streams to object streams. + if (info.is_object_stream_flag) { return; + } info.type = ObjectType::kCompressed; info.archive.obj_num = archive_obj_num; info.archive.obj_index = archive_obj_index; info.gennum = 0; - objects_info_[archive_obj_num].type = ObjectType::kObjStream; + objects_info_[archive_obj_num].is_object_stream_flag = true; } void CPDF_CrossRefTable::AddNormal(uint32_t obj_num, uint16_t gen_num, + bool is_object_stream, FX_FILESIZE pos) { CHECK_LT(obj_num, CPDF_Parser::kMaxObjectNumber); @@ -67,9 +70,8 @@ if (info.type == ObjectType::kCompressed && gen_num == 0) return; - if (info.type != ObjectType::kObjStream) - info.type = ObjectType::kNormal; - + info.type = ObjectType::kNormal; + info.is_object_stream_flag |= is_object_stream; info.gennum = gen_num; info.pos = pos; } @@ -129,9 +131,10 @@ auto new_it = new_objects_info.begin(); while (cur_it != objects_info_.end() && new_it != new_objects_info.end()) { if (cur_it->first == new_it->first) { - if (cur_it->second.type == ObjectType::kObjStream && - new_it->second.type == ObjectType::kNormal) { - new_it->second.type = ObjectType::kObjStream; + if (new_it->second.type == ObjectType::kNormal && + cur_it->second.type == ObjectType::kNormal && + cur_it->second.is_object_stream_flag) { + new_it->second.is_object_stream_flag = true; } ++cur_it; ++new_it;
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_table.h b/core/fpdfapi/parser/cpdf_cross_ref_table.h index 5fdc415..725d407 100644 --- a/core/fpdfapi/parser/cpdf_cross_ref_table.h +++ b/core/fpdfapi/parser/cpdf_cross_ref_table.h
@@ -17,16 +17,17 @@ class CPDF_CrossRefTable { public: + // See ISO 32000-1:2008 table 18. enum class ObjectType : uint8_t { - kFree = 0x00, - kNormal = 0x01, - kCompressed = 0x02, - kObjStream = 0xFF, - kNull = kObjStream, + kFree = 0, + kNormal = 1, + kCompressed = 2, + kNull = 3, // Higher values reserved, treat all as the null object. }; struct ObjectInfo { ObjectType type = ObjectType::kFree; + bool is_object_stream_flag = false; uint16_t gennum = 0; // If `type` is `ObjectType::kCompressed`, `archive` should be used. // If `type` is `ObjectType::kNormal`, `pos` should be used. @@ -53,7 +54,10 @@ void AddCompressed(uint32_t obj_num, uint32_t archive_obj_num, uint32_t archive_obj_index); - void AddNormal(uint32_t obj_num, uint16_t gen_num, FX_FILESIZE pos); + void AddNormal(uint32_t obj_num, + uint16_t gen_num, + bool is_object_stream, + FX_FILESIZE pos); void SetFree(uint32_t obj_num); void SetTrailer(RetainPtr<CPDF_Dictionary> trailer,
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp index c8136e7..f1d9cbc 100644 --- a/core/fpdfapi/parser/cpdf_parser.cpp +++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -652,13 +652,17 @@ m_CrossRefTable->SetFree(obj.obj_num); break; case ObjectType::kNormal: - case ObjectType::kObjStream: - m_CrossRefTable->AddNormal(obj.obj_num, obj.info.gennum, obj.info.pos); + m_CrossRefTable->AddNormal(obj.obj_num, obj.info.gennum, + obj.info.is_object_stream_flag, + obj.info.pos); break; case ObjectType::kCompressed: m_CrossRefTable->AddCompressed(obj.obj_num, obj.info.archive.obj_num, obj.info.archive.obj_index); break; + case ObjectType::kNull: + // Ignored. + break; } } } @@ -745,7 +749,8 @@ } if (obj_num < kMaxObjectNumber) { - cross_ref_table->AddNormal(obj_num, gen_num, obj_pos); + cross_ref_table->AddNormal(obj_num, gen_num, /*is_object_stream=*/false, + obj_pos); const auto object_stream = CPDF_ObjectStream::Create(std::move(pStream)); if (object_stream) { @@ -891,7 +896,8 @@ if (existing_type == ObjectType::kNull) { const uint32_t offset = GetSecondXRefStreamEntry(entry_span, field_widths); if (pdfium::base::IsValueInRangeForNumericType<FX_FILESIZE>(offset)) - m_CrossRefTable->AddNormal(obj_num, 0, offset); + m_CrossRefTable->AddNormal(obj_num, 0, /*is_object_stream=*/false, + offset); return; } @@ -907,7 +913,8 @@ if (type == ObjectType::kNormal) { const uint32_t offset = GetSecondXRefStreamEntry(entry_span, field_widths); if (pdfium::base::IsValueInRangeForNumericType<FX_FILESIZE>(offset)) - m_CrossRefTable->AddNormal(obj_num, 0, offset); + m_CrossRefTable->AddNormal(obj_num, 0, /*is_object_stream=*/false, + offset); return; } @@ -1028,7 +1035,7 @@ return it->second.get(); const auto* info = m_CrossRefTable->GetObjectInfo(object_number); - if (!info || info->type != ObjectType::kObjStream) { + if (!info || !info->is_object_stream_flag) { return nullptr; }
diff --git a/core/fpdfapi/parser/cpdf_parser_unittest.cpp b/core/fpdfapi/parser/cpdf_parser_unittest.cpp index 801217f..114fb29 100644 --- a/core/fpdfapi/parser/cpdf_parser_unittest.cpp +++ b/core/fpdfapi/parser/cpdf_parser_unittest.cpp
@@ -66,7 +66,7 @@ case CPDF_CrossRefTable::ObjectType::kCompressed: return lhs.archive.obj_num == rhs.archive.obj_num && lhs.archive.obj_index == rhs.archive.obj_index; - case CPDF_CrossRefTable::ObjectType::kObjStream: + case CPDF_CrossRefTable::ObjectType::kNull: return false; } } @@ -81,14 +81,15 @@ os << "Free object"; break; case CPDF_CrossRefTable::ObjectType::kNormal: - os << "Normal object, pos: " << info.pos; + os << "Normal object, pos: " << info.pos + << ", obj_stream=" << info.is_object_stream_flag; break; case CPDF_CrossRefTable::ObjectType::kCompressed: os << "Compressed object, archive obj_num: " << info.archive.obj_num << ", archive obj_index: " << info.archive.obj_index; break; - case CPDF_CrossRefTable::ObjectType::kObjStream: - os << "ObjectStream object"; + case CPDF_CrossRefTable::ObjectType::kNull: + os << "Null object"; break; } os << ", gennum: " << info.gennum << ")";