Avoid a redundant header offset check in CPDF_Parser.

CPDF_Parser::StartLinearizedParse() calls StartParse(), but already
knows the PDF header offset. Refactor StartParse() so it does not have
to look for the header again.
Change-Id: Id8cc39301ae72da868dafc53921622d5b28ce26e
Reviewed-on: https://pdfium-review.googlesource.com/9830
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Art Snake <art-snake@yandex-team.ru>
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp
index 88755a9..46c71a5 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_data_avail.cpp
@@ -754,7 +754,7 @@
   auto file = pdfium::MakeRetain<CFX_MemoryStream>(
       pData, static_cast<size_t>(dwLen), false);
   int32_t offset = GetHeaderOffset(file);
-  if (offset == -1) {
+  if (offset == kInvalidHeaderOffset) {
     m_docStatus = PDF_DATAAVAIL_ERROR;
     return false;
   }
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index e33cec0..d669f24 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -148,14 +148,26 @@
 CPDF_Parser::Error CPDF_Parser::StartParse(
     const CFX_RetainPtr<IFX_SeekableReadStream>& pFileAccess,
     CPDF_Document* pDocument) {
+  return StartParseInternal(pFileAccess, pDocument, kInvalidHeaderOffset);
+}
+
+CPDF_Parser::Error CPDF_Parser::StartParseInternal(
+    const CFX_RetainPtr<IFX_SeekableReadStream>& pFileAccess,
+    CPDF_Document* pDocument,
+    int32_t iHeaderOffset) {
   ASSERT(!m_bHasParsed);
   m_bHasParsed = true;
   m_bXRefStream = false;
   m_LastXRefOffset = 0;
 
-  int32_t offset = GetHeaderOffset(pFileAccess);
-  if (offset == -1)
-    return FORMAT_ERROR;
+  int32_t offset;
+  if (iHeaderOffset == kInvalidHeaderOffset) {
+    offset = GetHeaderOffset(pFileAccess);
+    if (offset == kInvalidHeaderOffset)
+      return FORMAT_ERROR;
+  } else {
+    offset = iHeaderOffset;
+  }
 
   m_pSyntax->InitParser(pFileAccess, offset);
 
@@ -1521,12 +1533,12 @@
   m_LastXRefOffset = 0;
 
   int32_t offset = GetHeaderOffset(pFileAccess);
-  if (offset == -1)
+  if (offset == kInvalidHeaderOffset)
     return FORMAT_ERROR;
 
-  if (!IsLinearizedFile(pFileAccess, offset)) {
-    return StartParse(pFileAccess, std::move(pDocument));
-  }
+  if (!IsLinearizedFile(pFileAccess, offset))
+    return StartParseInternal(pFileAccess, std::move(pDocument), offset);
+
   m_bHasParsed = true;
   m_pDocument = pDocument;
 
diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h
index 759d042..189de16 100644
--- a/core/fpdfapi/parser/cpdf_parser.h
+++ b/core/fpdfapi/parser/cpdf_parser.h
@@ -153,6 +153,9 @@
     ObjectInfo info;
   };
 
+  Error StartParseInternal(const CFX_RetainPtr<IFX_SeekableReadStream>& pFile,
+                           CPDF_Document* pDocument,
+                           int32_t iHeaderOffset);
   CPDF_Object* ParseDirect(CPDF_Object* pObj);
   bool LoadAllCrossRefV4(FX_FILESIZE pos);
   bool LoadAllCrossRefV5(FX_FILESIZE pos);
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.cpp b/core/fpdfapi/parser/fpdf_parser_utility.cpp
index 8323426..0c0ca66 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_utility.cpp
@@ -75,12 +75,12 @@
   uint8_t buf[kBufSize];
   for (int32_t offset = 0; offset <= 1024; ++offset) {
     if (!pFile->ReadBlock(buf, offset, kBufSize))
-      return -1;
+      return kInvalidHeaderOffset;
 
     if (memcmp(buf, "%PDF", 4) == 0)
       return offset;
   }
-  return -1;
+  return kInvalidHeaderOffset;
 }
 
 int32_t GetDirectInteger(CPDF_Dictionary* pDict, const CFX_ByteString& key) {
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.h b/core/fpdfapi/parser/fpdf_parser_utility.h
index eb8442a..5e764ad 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.h
+++ b/core/fpdfapi/parser/fpdf_parser_utility.h
@@ -34,7 +34,13 @@
   return c == '\r' || c == '\n';
 }
 
+constexpr int32_t kInvalidHeaderOffset = -1;
+
+// On success, return a positive offset value to the PDF header.. If the header
+// cannot be found, or if there is an error reading from |pFile|, then return
+// |kInvalidHeaderOffset|.
 int32_t GetHeaderOffset(const CFX_RetainPtr<IFX_SeekableReadStream>& pFile);
+
 int32_t GetDirectInteger(CPDF_Dictionary* pDict, const CFX_ByteString& key);
 
 CFX_ByteTextBuf& operator<<(CFX_ByteTextBuf& buf, const CPDF_Object* pObj);