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 << ")";