Avoid crashing inside FPDF_LoadCustomDocument().

Also change CPDFSDK_CustomAccess to use the provided FPDF_FILEACCESS
instead of making a copy.

Change-Id: I07a3e6b9e6af721d56e0b041c37ed373cff4acf3
Reviewed-on: https://pdfium-review.googlesource.com/c/47550
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_customaccess.cpp b/fpdfsdk/cpdfsdk_customaccess.cpp
index 1002085..b679858 100644
--- a/fpdfsdk/cpdfsdk_customaccess.cpp
+++ b/fpdfsdk/cpdfsdk_customaccess.cpp
@@ -7,12 +7,14 @@
 #include "fpdfsdk/cpdfsdk_customaccess.h"
 
 CPDFSDK_CustomAccess::CPDFSDK_CustomAccess(FPDF_FILEACCESS* pFileAccess)
-    : m_FileAccess(*pFileAccess) {}
+    : m_pFileAccess(pFileAccess) {
+  ASSERT(m_pFileAccess);
+}
 
 CPDFSDK_CustomAccess::~CPDFSDK_CustomAccess() = default;
 
 FX_FILESIZE CPDFSDK_CustomAccess::GetSize() {
-  return m_FileAccess.m_FileLen;
+  return m_pFileAccess->m_FileLen;
 }
 
 bool CPDFSDK_CustomAccess::ReadBlockAtOffset(void* buffer,
@@ -21,12 +23,13 @@
   if (offset < 0)
     return false;
 
-  FX_SAFE_FILESIZE newPos = pdfium::base::checked_cast<FX_FILESIZE>(size);
-  newPos += offset;
-  if (!newPos.IsValid() ||
-      newPos.ValueOrDie() > static_cast<FX_FILESIZE>(m_FileAccess.m_FileLen)) {
+  FX_SAFE_FILESIZE new_pos = pdfium::base::checked_cast<FX_FILESIZE>(size);
+  new_pos += offset;
+  if (!new_pos.IsValid())
     return false;
-  }
-  return !!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset,
-                                   static_cast<uint8_t*>(buffer), size);
+  if (new_pos.ValueOrDie() > static_cast<FX_FILESIZE>(m_pFileAccess->m_FileLen))
+    return false;
+
+  return !!m_pFileAccess->m_GetBlock(m_pFileAccess->m_Param, offset,
+                                     static_cast<uint8_t*>(buffer), size);
 }
diff --git a/fpdfsdk/cpdfsdk_customaccess.h b/fpdfsdk/cpdfsdk_customaccess.h
index 76940ce..341d4ab 100644
--- a/fpdfsdk/cpdfsdk_customaccess.h
+++ b/fpdfsdk/cpdfsdk_customaccess.h
@@ -25,7 +25,7 @@
   explicit CPDFSDK_CustomAccess(FPDF_FILEACCESS* pFileAccess);
   ~CPDFSDK_CustomAccess() override;
 
-  FPDF_FILEACCESS m_FileAccess;
+  UnownedPtr<FPDF_FILEACCESS> const m_pFileAccess;
 };
 
 #endif  // FPDFSDK_CPDFSDK_CUSTOMACCESS_H_
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index f4c1515..571f6eb 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -267,6 +267,8 @@
 FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
 FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
                         FPDF_BYTESTRING password) {
+  if (!pFileAccess)
+    return nullptr;
   return LoadDocumentImpl(pdfium::MakeRetain<CPDFSDK_CustomAccess>(pFileAccess),
                           password);
 }
diff --git a/fpdfsdk/fpdf_view_embeddertest.cpp b/fpdfsdk/fpdf_view_embeddertest.cpp
index 301eaa3..9de00c5 100644
--- a/fpdfsdk/fpdf_view_embeddertest.cpp
+++ b/fpdfsdk/fpdf_view_embeddertest.cpp
@@ -107,6 +107,10 @@
   EXPECT_EQ(16, version);
 }
 
+TEST_F(FPDFViewEmbedderTest, LoadCustomDocumentWithoutFileAccess) {
+  EXPECT_FALSE(FPDF_LoadCustomDocument(nullptr, ""));
+}
+
 TEST_F(FPDFViewEmbedderTest, Page) {
   EXPECT_TRUE(OpenDocument("about_blank.pdf"));
   FPDF_PAGE page = LoadPage(0);