summaryrefslogtreecommitdiff
path: root/core/fpdfapi
diff options
context:
space:
mode:
Diffstat (limited to 'core/fpdfapi')
-rw-r--r--core/fpdfapi/fpdf_parser/cpdf_parser.cpp28
-rw-r--r--core/fpdfapi/fpdf_parser/cpdf_parser_embeddertest.cpp16
-rw-r--r--core/fpdfapi/fpdf_parser/include/cpdf_parser.h3
3 files changed, 47 insertions, 0 deletions
diff --git a/core/fpdfapi/fpdf_parser/cpdf_parser.cpp b/core/fpdfapi/fpdf_parser/cpdf_parser.cpp
index 1ec912ebee..acf51de1ea 100644
--- a/core/fpdfapi/fpdf_parser/cpdf_parser.cpp
+++ b/core/fpdfapi/fpdf_parser/cpdf_parser.cpp
@@ -316,6 +316,32 @@ FX_FILESIZE CPDF_Parser::GetObjectOffset(uint32_t objnum) const {
return 0;
}
+// Ideally, all the cross reference entries should be verified.
+// In reality, we rarely see well-formed cross references don't match
+// with the objects. crbug/602650 showed a case where object numbers
+// in the cross reference table are all off by one.
+bool CPDF_Parser::VerifyCrossRefV4() {
+ for (const auto& it : m_ObjectInfo) {
+ if (it.second.pos == 0)
+ continue;
+ // Find the first non-zero position.
+ FX_FILESIZE SavedPos = m_pSyntax->SavePos();
+ m_pSyntax->RestorePos(it.second.pos);
+ bool is_num = false;
+ CFX_ByteString num_str = m_pSyntax->GetNextWord(&is_num);
+ m_pSyntax->RestorePos(SavedPos);
+ if (!is_num || num_str.IsEmpty() ||
+ FXSYS_atoui(num_str.c_str()) != it.first) {
+ // If the object number read doesn't match the one stored,
+ // something is wrong with the cross reference table.
+ return false;
+ } else {
+ return true;
+ }
+ }
+ return true;
+}
+
FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) {
if (!LoadCrossRefV4(xrefpos, 0, TRUE))
return FALSE;
@@ -366,6 +392,8 @@ FX_BOOL CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) {
for (size_t i = 0; i < CrossRefList.size(); ++i) {
if (!LoadCrossRefV4(CrossRefList[i], XRefStreamList[i], FALSE))
return FALSE;
+ if (i == 0 && !VerifyCrossRefV4())
+ return FALSE;
}
return TRUE;
}
diff --git a/core/fpdfapi/fpdf_parser/cpdf_parser_embeddertest.cpp b/core/fpdfapi/fpdf_parser/cpdf_parser_embeddertest.cpp
index f427ec5d81..042b221554 100644
--- a/core/fpdfapi/fpdf_parser/cpdf_parser_embeddertest.cpp
+++ b/core/fpdfapi/fpdf_parser/cpdf_parser_embeddertest.cpp
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "public/fpdf_text.h"
#include "testing/embedder_test.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -38,3 +39,18 @@ TEST_F(CPDFParserEmbeddertest, Bug_325) {
EXPECT_FALSE(OpenDocument("bug_325_a.pdf"));
EXPECT_FALSE(OpenDocument("bug_325_b.pdf"));
}
+
+TEST_F(CPDFParserEmbeddertest, Bug_602650) {
+ // Test the case that cross reference entries, which are well formed,
+ // but do not match with the objects.
+ EXPECT_TRUE(OpenDocument("bug_602650.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_NE(nullptr, page);
+ FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
+ EXPECT_NE(nullptr, text_page);
+ // The page should not be blank.
+ EXPECT_LT(0, FPDFText_CountChars(text_page));
+
+ FPDFText_ClosePage(text_page);
+ UnloadPage(page);
+}
diff --git a/core/fpdfapi/fpdf_parser/include/cpdf_parser.h b/core/fpdfapi/fpdf_parser/include/cpdf_parser.h
index 5331ccafb1..48511e9263 100644
--- a/core/fpdfapi/fpdf_parser/include/cpdf_parser.h
+++ b/core/fpdfapi/fpdf_parser/include/cpdf_parser.h
@@ -114,6 +114,9 @@ class CPDF_Parser {
FX_BOOL IsLinearizedFile(IFX_FileRead* pFileAccess, uint32_t offset);
void SetEncryptDictionary(CPDF_Dictionary* pDict);
void ShrinkObjectMap(uint32_t size);
+ // A simple check whether the cross reference table matches with
+ // the objects.
+ bool VerifyCrossRefV4();
CPDF_Document* m_pDocument;
std::unique_ptr<CPDF_SyntaxParser> m_pSyntax;