Refactoring of CPDF_DataAvail::AreObjectsAvailable.

Use ReadValidator to request exact data on object read.

Change-Id: Ie6c3f452e119fa3514e77f1824473c33bb6b855a
Reviewed-on: https://pdfium-review.googlesource.com/10491
Commit-Queue: Art Snake <art-snake@yandex-team.ru>
Reviewed-by: dsinclair <dsinclair@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp
index 46c71a5..2f17345 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_data_avail.cpp
@@ -52,17 +52,17 @@
   return nullptr;
 }
 
-class HintsAssigner {
+class HintsScope {
  public:
-  HintsAssigner(CPDF_ReadValidator* validator,
-                CPDF_DataAvail::DownloadHints* hints)
+  HintsScope(CPDF_ReadValidator* validator,
+             CPDF_DataAvail::DownloadHints* hints)
       : validator_(validator) {
     ASSERT(validator_);
     validator_->ResetErrors();
     validator_->SetDownloadHints(hints);
   }
 
-  ~HintsAssigner() { validator_->SetDownloadHints(nullptr); }
+  ~HintsScope() { validator_->SetDownloadHints(nullptr); }
 
  private:
   CFX_UnownedPtr<CPDF_ReadValidator> validator_;
@@ -155,7 +155,6 @@
 
 bool CPDF_DataAvail::AreObjectsAvailable(std::vector<CPDF_Object*>& obj_array,
                                          bool bParsePage,
-                                         DownloadHints* pHints,
                                          std::vector<CPDF_Object*>& ret_array) {
   if (obj_array.empty())
     return true;
@@ -188,24 +187,25 @@
         break;
       }
       case CPDF_Object::REFERENCE: {
-        CPDF_Reference* pRef = pObj->AsReference();
-        uint32_t dwNum = pRef->GetRefObjNum();
+        const CPDF_ReadValidator::Session read_session(GetValidator().Get());
 
-        FX_FILESIZE offset;
-        uint32_t size = GetObjectSize(dwNum, offset);
-        if (size == 0 || offset < 0 || offset >= m_dwFileLen)
+        CPDF_Reference* pRef = pObj->AsReference();
+        const uint32_t dwNum = pRef->GetRefObjNum();
+
+        if (pdfium::ContainsKey(m_ObjectSet, dwNum))
           break;
 
-        if (!IsDataAvail(offset, size, pHints)) {
+        CPDF_Object* pReferred = m_pDocument->GetOrParseIndirectObject(dwNum);
+        if (GetValidator()->has_read_problems()) {
+          ASSERT(!pReferred);
           ret_array.push_back(pObj);
-          count++;
-        } else if (!pdfium::ContainsKey(m_ObjectSet, dwNum)) {
-          m_ObjectSet.insert(dwNum);
-          CPDF_Object* pReferred =
-              m_pDocument->GetOrParseIndirectObject(pRef->GetRefObjNum());
-          if (pReferred)
-            new_obj_array.push_back(pReferred);
+          ++count;
+          break;
         }
+        m_ObjectSet.insert(dwNum);
+        if (pReferred)
+          new_obj_array.push_back(pReferred);
+
         break;
       }
     }
@@ -222,7 +222,7 @@
   }
 
   obj_array = new_obj_array;
-  return AreObjectsAvailable(obj_array, false, pHints, ret_array);
+  return AreObjectsAvailable(obj_array, false, ret_array);
 }
 
 CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::IsDocAvail(
@@ -230,7 +230,7 @@
   if (!m_dwFileLen)
     return DataError;
 
-  const HintsAssigner hints_assigner(m_pFileRead.Get(), pHints);
+  const HintsScope hints_scope(m_pFileRead.Get(), pHints);
 
   while (!m_bDocAvail) {
     if (!CheckDocStatus(pHints))
@@ -240,7 +240,7 @@
   return DataAvailable;
 }
 
-bool CPDF_DataAvail::CheckAcroFormSubObject(DownloadHints* pHints) {
+bool CPDF_DataAvail::CheckAcroFormSubObject() {
   if (m_objs_array.empty()) {
     std::vector<CPDF_Object*> obj_array(m_Acroforms.size());
     std::transform(
@@ -248,7 +248,7 @@
         [](const std::unique_ptr<CPDF_Object>& pObj) { return pObj.get(); });
 
     m_ObjectSet.clear();
-    if (!AreObjectsAvailable(obj_array, false, pHints, m_objs_array))
+    if (!AreObjectsAvailable(obj_array, false, m_objs_array))
       return false;
 
     m_objs_array.clear();
@@ -256,7 +256,7 @@
   }
 
   std::vector<CPDF_Object*> new_objs_array;
-  if (!AreObjectsAvailable(m_objs_array, false, pHints, new_objs_array)) {
+  if (!AreObjectsAvailable(m_objs_array, false, new_objs_array)) {
     m_objs_array = new_objs_array;
     return false;
   }
@@ -1392,7 +1392,7 @@
   return m_bLinearedDataOK ? DataAvailable : DataNotAvailable;
 }
 
-bool CPDF_DataAvail::CheckPageAnnots(uint32_t dwPage, DownloadHints* pHints) {
+bool CPDF_DataAvail::CheckPageAnnots(uint32_t dwPage) {
   if (m_objs_array.empty()) {
     m_ObjectSet.clear();
 
@@ -1407,7 +1407,7 @@
 
     std::vector<CPDF_Object*> obj_array;
     obj_array.push_back(pAnnots);
-    if (!AreObjectsAvailable(obj_array, false, pHints, m_objs_array))
+    if (!AreObjectsAvailable(obj_array, false, m_objs_array))
       return false;
 
     m_objs_array.clear();
@@ -1415,7 +1415,7 @@
   }
 
   std::vector<CPDF_Object*> new_objs_array;
-  if (!AreObjectsAvailable(m_objs_array, false, pHints, new_objs_array)) {
+  if (!AreObjectsAvailable(m_objs_array, false, new_objs_array)) {
     m_objs_array = new_objs_array;
     return false;
   }
@@ -1424,10 +1424,9 @@
 }
 
 CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckLinearizedFirstPage(
-    uint32_t dwPage,
-    DownloadHints* pHints) {
+    uint32_t dwPage) {
   if (!m_bAnnotsLoad) {
-    if (!CheckPageAnnots(dwPage, pHints))
+    if (!CheckPageAnnots(dwPage))
       return DataNotAvailable;
     m_bAnnotsLoad = true;
   }
@@ -1454,9 +1453,11 @@
   if (pdfium::ContainsKey(m_pagesLoadState, dwPage))
     return DataAvailable;
 
+  const HintsScope hints_scope(GetValidator().Get(), pHints);
+
   if (m_pLinearized) {
     if (dwPage == m_pLinearized->GetFirstPageNo()) {
-      DocAvailStatus nRet = CheckLinearizedFirstPage(dwPage, pHints);
+      DocAvailStatus nRet = CheckLinearizedFirstPage(dwPage);
       if (nRet == DataAvailable)
         m_pagesLoadState.insert(dwPage);
       return nRet;
@@ -1496,7 +1497,7 @@
   }
 
   if (m_bHaveAcroForm && !m_bAcroFormLoad) {
-    if (!CheckAcroFormSubObject(pHints))
+    if (!CheckAcroFormSubObject())
       return DataNotAvailable;
     m_bAcroFormLoad = true;
   }
@@ -1515,13 +1516,13 @@
 
       std::vector<CPDF_Object*> obj_array;
       obj_array.push_back(m_pPageDict);
-      if (!AreObjectsAvailable(obj_array, true, pHints, m_objs_array))
+      if (!AreObjectsAvailable(obj_array, true, m_objs_array))
         return DataNotAvailable;
 
       m_objs_array.clear();
     } else {
       std::vector<CPDF_Object*> new_objs_array;
-      if (!AreObjectsAvailable(m_objs_array, false, pHints, new_objs_array)) {
+      if (!AreObjectsAvailable(m_objs_array, false, new_objs_array)) {
         m_objs_array = new_objs_array;
         return DataNotAvailable;
       }
@@ -1531,7 +1532,7 @@
   }
 
   if (!m_bAnnotsLoad) {
-    if (!CheckPageAnnots(dwPage, pHints))
+    if (!CheckPageAnnots(dwPage))
       return DataNotAvailable;
     m_bAnnotsLoad = true;
   }
@@ -1542,7 +1543,7 @@
   }
 
   if (m_bNeedDownLoadResource) {
-    if (!CheckResources(pHints))
+    if (!CheckResources())
       return DataNotAvailable;
     m_bNeedDownLoadResource = false;
   }
@@ -1558,18 +1559,18 @@
   return DataAvailable;
 }
 
-bool CPDF_DataAvail::CheckResources(DownloadHints* pHints) {
+bool CPDF_DataAvail::CheckResources() {
   if (m_objs_array.empty()) {
     std::vector<CPDF_Object*> obj_array;
     obj_array.push_back(m_pPageResource);
-    if (!AreObjectsAvailable(obj_array, true, pHints, m_objs_array))
+    if (!AreObjectsAvailable(obj_array, true, m_objs_array))
       return false;
 
     m_objs_array.clear();
     return true;
   }
   std::vector<CPDF_Object*> new_objs_array;
-  if (!AreObjectsAvailable(m_objs_array, false, pHints, new_objs_array)) {
+  if (!AreObjectsAvailable(m_objs_array, false, new_objs_array)) {
     m_objs_array = new_objs_array;
     return false;
   }
@@ -1581,6 +1582,10 @@
   return m_pFileRead;
 }
 
+CFX_RetainPtr<CPDF_ReadValidator> CPDF_DataAvail::GetValidator() const {
+  return m_pFileRead;
+}
+
 int CPDF_DataAvail::GetPageCount() const {
   if (m_pLinearized)
     return m_pLinearized->GetPageCount();
@@ -1623,6 +1628,8 @@
     DownloadHints* pHints) {
   if (!m_pDocument)
     return FormAvailable;
+
+  const HintsScope hints_scope(GetValidator().Get(), pHints);
   if (m_pLinearized) {
     DocAvailStatus nDocStatus = CheckLinearizedData(pHints);
     if (nDocStatus == DataError)
@@ -1645,7 +1652,7 @@
   }
 
   std::vector<CPDF_Object*> new_objs_array;
-  if (!AreObjectsAvailable(m_objs_array, false, pHints, new_objs_array)) {
+  if (!AreObjectsAvailable(m_objs_array, false, new_objs_array)) {
     m_objs_array = new_objs_array;
     return FormNotAvailable;
   }
@@ -1664,7 +1671,7 @@
   std::vector<CPDF_Object*> obj_array;
   obj_array.push_back(pPageDict);
   std::vector<CPDF_Object*> dummy;
-  return AreObjectsAvailable(obj_array, true, nullptr, dummy);
+  return AreObjectsAvailable(obj_array, true, dummy);
 }
 
 bool CPDF_DataAvail::ValidateForm() {
@@ -1677,7 +1684,7 @@
   std::vector<CPDF_Object*> obj_array;
   obj_array.push_back(pAcroForm);
   std::vector<CPDF_Object*> dummy;
-  return AreObjectsAvailable(obj_array, true, nullptr, dummy);
+  return AreObjectsAvailable(obj_array, true, dummy);
 }
 
 CPDF_DataAvail::PageNode::PageNode() : m_type(PDF_PAGENODE_UNKNOWN) {}
diff --git a/core/fpdfapi/parser/cpdf_data_avail.h b/core/fpdfapi/parser/cpdf_data_avail.h
index f19b36d..b857c65 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.h
+++ b/core/fpdfapi/parser/cpdf_data_avail.h
@@ -111,6 +111,7 @@
   CFX_RetainPtr<IFX_SeekableReadStream> GetFileRead() const;
   int GetPageCount() const;
   CPDF_Dictionary* GetPage(int index);
+  CFX_RetainPtr<CPDF_ReadValidator> GetValidator() const;
 
  protected:
   class PageNode {
@@ -128,7 +129,6 @@
   uint32_t GetObjectSize(uint32_t objnum, FX_FILESIZE& offset);
   bool AreObjectsAvailable(std::vector<CPDF_Object*>& obj_array,
                            bool bParsePage,
-                           DownloadHints* pHints,
                            std::vector<CPDF_Object*>& ret_array);
   bool CheckDocStatus(DownloadHints* pHints);
   bool CheckHeader(DownloadHints* pHints);
@@ -142,10 +142,10 @@
   bool CheckInfo(DownloadHints* pHints);
   bool CheckPages(DownloadHints* pHints);
   bool CheckPage(DownloadHints* pHints);
-  bool CheckResources(DownloadHints* pHints);
+  bool CheckResources();
   bool CheckAnnots(DownloadHints* pHints);
   bool CheckAcroForm(DownloadHints* pHints);
-  bool CheckAcroFormSubObject(DownloadHints* pHints);
+  bool CheckAcroFormSubObject();
   bool CheckTrailerAppend(DownloadHints* pHints);
   bool CheckPageStatus(DownloadHints* pHints);
   bool CheckAllCrossRefStream(DownloadHints* pHints);
@@ -168,10 +168,9 @@
   bool LoadAllXref(DownloadHints* pHints);
   bool LoadAllFile(DownloadHints* pHints);
   DocAvailStatus CheckLinearizedData(DownloadHints* pHints);
-  bool CheckPageAnnots(uint32_t dwPage, DownloadHints* pHints);
+  bool CheckPageAnnots(uint32_t dwPage);
 
-  DocAvailStatus CheckLinearizedFirstPage(uint32_t dwPage,
-                                          DownloadHints* pHints);
+  DocAvailStatus CheckLinearizedFirstPage(uint32_t dwPage);
   bool CheckPage(uint32_t dwPage, DownloadHints* pHints);
   bool LoadDocPages(DownloadHints* pHints);
   bool LoadDocPage(uint32_t dwPage, DownloadHints* pHints);