Limit xref size in CPDF_Parser::LoadCrossRefStream()
Check the size against `kMaxXRefSize` before calling
CPDF_CrossRefTable::SetObjectMapSize(), like the other caller for
SetObjectMapSize().
Bug: 439237853
Change-Id: Ib1bae822fc84c1c503d722669c922d36a6076b6b
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/135470
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index ec6d99f..782e88c 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -844,13 +844,19 @@
}
RetainPtr<const CPDF_Dictionary> dict = pStream->GetDict();
- int32_t prev = dict->GetIntegerFor("Prev");
+ const int32_t prev = dict->GetIntegerFor("Prev");
if (prev < 0) {
return false;
}
- int32_t size = dict->GetIntegerFor("Size");
- if (size < 0) {
+ // If /Size is negative or way too big, then it is obvious wrong.
+ // Immediately reject these cases, so `cross_ref_table_` does not get into a
+ // bad state.
+ //
+ // For a /Size of 0 or other issues, just ignore them. See comments in the
+ // for-loop below.
+ const int32_t size = dict->GetIntegerFor("Size");
+ if (size < 0 || size >= kMaxXRefSize) {
return false;
}
diff --git a/core/fpdfapi/parser/cpdf_parser_unittest.cpp b/core/fpdfapi/parser/cpdf_parser_unittest.cpp
index ea46152..f212c69 100644
--- a/core/fpdfapi/parser/cpdf_parser_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_parser_unittest.cpp
@@ -481,25 +481,7 @@
"14\n"
"%%EOF\n";
ASSERT_TRUE(parser().InitTestFromBuffer(kData));
- EXPECT_EQ(CPDF_Parser::SUCCESS, parser().StartParseInternal());
- EXPECT_FALSE(parser().xref_table_rebuilt());
- ASSERT_TRUE(parser().GetCrossRefTableForTesting());
- const auto& objects_info =
- parser().GetCrossRefTableForTesting()->objects_info();
-
- // This should be the only object from table. Subsequent objects have object
- // numbers that are too big.
- const CPDF_CrossRefTable::ObjectInfo only_valid_object = {
- .type = CPDF_CrossRefTable::ObjectType::kNormal, .pos = 0};
-
- // TODO(thestig): Should the xref table contain object 4194304?
- // Consider reworking CPDF_Parser's object representation to avoid having to
- // store this placeholder object.
- const CPDF_CrossRefTable::ObjectInfo placeholder_object = {
- .type = CPDF_CrossRefTable::ObjectType::kFree, .pos = 0};
-
- EXPECT_THAT(objects_info, ElementsAre(Pair(4194303, only_valid_object),
- Pair(4194304, placeholder_object)));
+ EXPECT_EQ(CPDF_Parser::FORMAT_ERROR, parser().StartParseInternal());
}
TEST_F(ParserXRefTest, XrefObjectIndicesTooBig2) {
@@ -526,25 +508,7 @@
"14\n"
"%%EOF\n";
ASSERT_TRUE(parser().InitTestFromBuffer(kData));
- EXPECT_EQ(CPDF_Parser::SUCCESS, parser().StartParseInternal());
- EXPECT_FALSE(parser().xref_table_rebuilt());
- ASSERT_TRUE(parser().GetCrossRefTableForTesting());
- const auto& objects_info =
- parser().GetCrossRefTableForTesting()->objects_info();
-
- // This should be the only object from table. Subsequent objects have object
- // numbers that are too big.
- const CPDF_CrossRefTable::ObjectInfo only_valid_object = {
- .type = CPDF_CrossRefTable::ObjectType::kNormal, .pos = 0};
-
- // TODO(thestig): Should the xref table contain object 4194305?
- // Consider reworking CPDF_Parser's object representation to avoid having to
- // store this placeholder object.
- const CPDF_CrossRefTable::ObjectInfo placeholder_object = {
- .type = CPDF_CrossRefTable::ObjectType::kFree, .pos = 0};
-
- EXPECT_THAT(objects_info, ElementsAre(Pair(4194303, only_valid_object),
- Pair(4194305, placeholder_object)));
+ EXPECT_EQ(CPDF_Parser::FORMAT_ERROR, parser().StartParseInternal());
}
TEST_F(ParserXRefTest, XrefHasInvalidArchiveObjectNumber) {