Split public fuzzer static initializer into its own file

pdfium_fuzzer_helper.cc contained both logic for public fuzzers, and the
static initalizer for setting up pdfium.  So the fuzzers have a
dependency on pdfium_fuzzer_helper.cc, but in component builds, they get
linked into libpdfium.so.  We want to avoid adding the static initializer
to libpdfium.so, otherwise pdfium will get statically initialized
everywhere.

BUG=chromium:960288
R=thestig

Change-Id: Icc93615b83ffaa0343d2a875aa7b35459bba11ef
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/54353
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Auto-Submit: Thomas Anderson <thomasanderson@chromium.org>
diff --git a/testing/fuzzers/BUILD.gn b/testing/fuzzers/BUILD.gn
index a283927..038d2ce 100644
--- a/testing/fuzzers/BUILD.gn
+++ b/testing/fuzzers/BUILD.gn
@@ -108,6 +108,7 @@
     sources = invoker.sources + [
                 "pdfium_fuzzer_helper.cc",
                 "pdfium_fuzzer_helper.h",
+                "pdf_fuzzer_init_public.cc",
               ]
     deps = [
       "../:test_support",
diff --git a/testing/fuzzers/pdf_fuzzer_init.cc b/testing/fuzzers/pdf_fuzzer_init.cc
index d6b10ff..954eed0 100644
--- a/testing/fuzzers/pdf_fuzzer_init.cc
+++ b/testing/fuzzers/pdf_fuzzer_init.cc
@@ -19,7 +19,7 @@
   FPDF_LIBRARY_CONFIG config;
 };
 
-// pdf_fuzzer_init.cc and pdfium_fuzzer_helper.cc are mutually exclusive and
-// should not be built together. They deliberately have the same global
+// pdf_fuzzer_init.cc and pdfium_fuzzer_init_public.cc are mutually exclusive
+// and should not be built together. They deliberately have the same global
 // variable.
 static TestCase* g_test_case = new TestCase();
diff --git a/testing/fuzzers/pdf_fuzzer_init_public.cc b/testing/fuzzers/pdf_fuzzer_init_public.cc
new file mode 100644
index 0000000..63bf6ae
--- /dev/null
+++ b/testing/fuzzers/pdf_fuzzer_init_public.cc
@@ -0,0 +1,96 @@
+// Copyright 2019 The PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string.h>
+
+#include <memory>
+
+#include "public/fpdf_ext.h"
+
+#ifdef PDF_ENABLE_V8
+#include "testing/free_deleter.h"
+#include "testing/v8_initializer.h"
+#include "v8/include/v8-platform.h"
+#include "v8/include/v8.h"
+#endif
+
+#ifdef _WIN32
+#include <Windows.h>
+#elif defined(__APPLE__)
+#include <mach-o/dyld.h>
+#else  // Linux
+#include <unistd.h>
+#endif  // _WIN32
+
+namespace {
+
+#ifdef PDF_ENABLE_V8
+std::string ProgramPath() {
+  std::string result;
+
+#ifdef _WIN32
+  char path[MAX_PATH];
+  DWORD len = GetModuleFileNameA(NULL, path, MAX_PATH);
+  if (len != 0)
+    result = std::string(path, len);
+#elif defined(__APPLE__)
+  char path[PATH_MAX];
+  unsigned int len = PATH_MAX;
+  if (!_NSGetExecutablePath(path, &len)) {
+    std::unique_ptr<char, pdfium::FreeDeleter> resolved_path(
+        realpath(path, nullptr));
+    if (resolved_path.get())
+      result = std::string(resolved_path.get());
+  }
+#else  // Linux
+  char path[PATH_MAX];
+  ssize_t len = readlink("/proc/self/exe", path, PATH_MAX);
+  if (len > 0)
+    result = std::string(path, len);
+#endif
+  return result;
+}
+#endif  // PDF_ENABLE_V8
+
+}  // namespace
+
+// Initialize the library once for all runs of the fuzzer.
+struct TestCase {
+  TestCase() {
+#ifdef PDF_ENABLE_V8
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+    platform = InitializeV8ForPDFiumWithStartupData(
+        ProgramPath(), "", &natives_blob, &snapshot_blob);
+#else
+    platform = InitializeV8ForPDFium(ProgramPath());
+#endif  // V8_USE_EXTERNAL_STARTUP_DATA
+#endif  // PDF_ENABLE_V8
+
+    memset(&config, '\0', sizeof(config));
+    config.version = 2;
+    config.m_pUserFontPaths = nullptr;
+    config.m_pIsolate = nullptr;
+    config.m_v8EmbedderSlot = 0;
+    FPDF_InitLibraryWithConfig(&config);
+
+    memset(&unsupport_info, '\0', sizeof(unsupport_info));
+    unsupport_info.version = 1;
+    unsupport_info.FSDK_UnSupport_Handler = [](UNSUPPORT_INFO*, int) {};
+    FSDK_SetUnSpObjProcessHandler(&unsupport_info);
+  }
+
+#ifdef PDF_ENABLE_V8
+  std::unique_ptr<v8::Platform> platform;
+  v8::StartupData natives_blob;
+  v8::StartupData snapshot_blob;
+#endif
+
+  FPDF_LIBRARY_CONFIG config;
+  UNSUPPORT_INFO unsupport_info;
+};
+
+// pdf_fuzzer_init.cc and pdfium_fuzzer_init_public.cc are mutually exclusive
+// and should not be built together. They deliberately have the same global
+// variable.
+static TestCase* g_test_case = new TestCase();
diff --git a/testing/fuzzers/pdfium_fuzzer_helper.cc b/testing/fuzzers/pdfium_fuzzer_helper.cc
index 3861034..27e0292 100644
--- a/testing/fuzzers/pdfium_fuzzer_helper.cc
+++ b/testing/fuzzers/pdfium_fuzzer_helper.cc
@@ -13,34 +13,42 @@
 #include <stdlib.h>
 #include <string.h>
 
-#ifdef _WIN32
-#include <Windows.h>
-#elif defined(__APPLE__)
-#include <mach-o/dyld.h>
-#else  // Linux
-#include <unistd.h>
-#endif  // _WIN32
-
 #include <memory>
 #include <sstream>
 #include <string>
+#include <tuple>
 #include <utility>
 
 #include "public/cpp/fpdf_scopers.h"
 #include "public/fpdf_dataavail.h"
 #include "public/fpdf_ext.h"
 #include "public/fpdf_text.h"
-#include "testing/test_loader.h"
-
-#ifdef PDF_ENABLE_V8
-#include "testing/free_deleter.h"
-#include "testing/v8_initializer.h"
-#include "v8/include/v8-platform.h"
-#include "v8/include/v8.h"
-#endif
+#include "third_party/base/span.h"
 
 namespace {
 
+class FuzzerTestLoader {
+ public:
+  explicit FuzzerTestLoader(pdfium::span<const char> span) : m_Span(span) {}
+
+  static int GetBlock(void* param,
+                      unsigned long pos,
+                      unsigned char* pBuf,
+                      unsigned long size) {
+    FuzzerTestLoader* pLoader = static_cast<FuzzerTestLoader*>(param);
+    if (pos + size < pos || pos + size > pLoader->m_Span.size()) {
+      NOTREACHED();
+      return 0;
+    }
+
+    memcpy(pBuf, &pLoader->m_Span[pos], size);
+    return 1;
+  }
+
+ private:
+  const pdfium::span<const char> m_Span;
+};
+
 int ExampleAppAlert(IPDF_JSPLATFORM*,
                     FPDF_WIDESTRING,
                     FPDF_WIDESTRING,
@@ -78,42 +86,12 @@
                     FPDF_WIDESTRING BCC,
                     FPDF_WIDESTRING Msg) {}
 
-void ExampleUnsupportedHandler(UNSUPPORT_INFO*, int type) {}
-
 FPDF_BOOL Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) {
   return true;
 }
 
 void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {}
 
-#ifdef PDF_ENABLE_V8
-std::string ProgramPath() {
-  std::string result;
-
-#ifdef _WIN32
-  char path[MAX_PATH];
-  DWORD len = GetModuleFileNameA(NULL, path, MAX_PATH);
-  if (len != 0)
-    result = std::string(path, len);
-#elif defined(__APPLE__)
-  char path[PATH_MAX];
-  unsigned int len = PATH_MAX;
-  if (!_NSGetExecutablePath(path, &len)) {
-    std::unique_ptr<char, pdfium::FreeDeleter> resolved_path(
-        realpath(path, nullptr));
-    if (resolved_path.get())
-      result = std::string(resolved_path.get());
-  }
-#else  // Linux
-  char path[PATH_MAX];
-  ssize_t len = readlink("/proc/self/exe", path, PATH_MAX);
-  if (len > 0)
-    result = std::string(path, len);
-#endif
-  return result;
-}
-#endif  // PDF_ENABLE_V8
-
 std::pair<int, int> GetRenderingAndFormFlagFromData(const char* data,
                                                     size_t len) {
   std::string data_str = std::string(data, len);
@@ -155,11 +133,11 @@
   form_callbacks.version = GetFormCallbackVersion();
   form_callbacks.m_pJsPlatform = &platform_callbacks;
 
-  TestLoader loader({data, len});
+  FuzzerTestLoader loader({data, len});
   FPDF_FILEACCESS file_access;
   memset(&file_access, '\0', sizeof(file_access));
   file_access.m_FileLen = static_cast<unsigned long>(len);
-  file_access.m_GetBlock = TestLoader::GetBlock;
+  file_access.m_GetBlock = FuzzerTestLoader::GetBlock;
   file_access.m_Param = &loader;
 
   FX_FILEAVAIL file_avail;
@@ -255,43 +233,3 @@
   FORM_OnBeforeClosePage(page.get(), form);
   return !!bitmap;
 }
-
-// Initialize the library once for all runs of the fuzzer.
-struct TestCase {
-  TestCase() {
-#ifdef PDF_ENABLE_V8
-#ifdef V8_USE_EXTERNAL_STARTUP_DATA
-    platform = InitializeV8ForPDFiumWithStartupData(
-        ProgramPath(), "", &natives_blob, &snapshot_blob);
-#else
-    platform = InitializeV8ForPDFium(ProgramPath());
-#endif  // V8_USE_EXTERNAL_STARTUP_DATA
-#endif  // PDF_ENABLE_V8
-
-    memset(&config, '\0', sizeof(config));
-    config.version = 2;
-    config.m_pUserFontPaths = nullptr;
-    config.m_pIsolate = nullptr;
-    config.m_v8EmbedderSlot = 0;
-    FPDF_InitLibraryWithConfig(&config);
-
-    memset(&unsupport_info, '\0', sizeof(unsupport_info));
-    unsupport_info.version = 1;
-    unsupport_info.FSDK_UnSupport_Handler = ExampleUnsupportedHandler;
-    FSDK_SetUnSpObjProcessHandler(&unsupport_info);
-  }
-
-#ifdef PDF_ENABLE_V8
-  std::unique_ptr<v8::Platform> platform;
-  v8::StartupData natives_blob;
-  v8::StartupData snapshot_blob;
-#endif
-
-  FPDF_LIBRARY_CONFIG config;
-  UNSUPPORT_INFO unsupport_info;
-};
-
-// pdf_fuzzer_init.cc and pdfium_fuzzer_helper.cc are mutually exclusive and
-// should not be built together. They deliberately have the same global
-// variable.
-static TestCase* g_test_case = new TestCase();