// Copyright 2019 The PDFium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "testing/v8_initializer.h" #include #include "public/fpdfview.h" #include "testing/utils/file_util.h" #include "testing/utils/path_service.h" #include "third_party/base/numerics/safe_conversions.h" #include "v8/include/libplatform/libplatform.h" #include "v8/include/v8-initialization.h" #include "v8/include/v8-snapshot.h" #ifdef PDF_ENABLE_XFA #include "v8/include/cppgc/platform.h" #endif namespace { #ifdef V8_USE_EXTERNAL_STARTUP_DATA // Returns the full path for an external V8 data file based on either // the currect exectuable path or an explicit override. std::string GetFullPathForSnapshotFile(const std::string& exe_path, const std::string& bin_dir, const std::string& filename) { std::string result; if (!bin_dir.empty()) { result = bin_dir; if (*bin_dir.rbegin() != PATH_SEPARATOR) { result += PATH_SEPARATOR; } } else if (!exe_path.empty()) { size_t last_separator = exe_path.rfind(PATH_SEPARATOR); if (last_separator != std::string::npos) { result = exe_path.substr(0, last_separator + 1); } } result += filename; return result; } bool GetExternalData(const std::string& exe_path, const std::string& bin_dir, const std::string& filename, v8::StartupData* result_data) { std::string full_path = GetFullPathForSnapshotFile(exe_path, bin_dir, filename); size_t data_length = 0; std::unique_ptr data_buffer = GetFileContents(full_path.c_str(), &data_length); if (!data_buffer) return false; result_data->data = data_buffer.release(); result_data->raw_size = pdfium::base::checked_cast(data_length); return true; } #endif // V8_USE_EXTERNAL_STARTUP_DATA std::unique_ptr InitializeV8Common(const std::string& exe_path, const std::string& js_flags) { v8::V8::InitializeICUDefaultLocation(exe_path.c_str()); std::unique_ptr platform = v8::platform::NewDefaultPlatform(); v8::V8::InitializePlatform(platform.get()); #ifdef PDF_ENABLE_XFA cppgc::InitializeProcess(platform->GetPageAllocator()); #endif const char* recommended_v8_flags = FPDF_GetRecommendedV8Flags(); v8::V8::SetFlagsFromString(recommended_v8_flags); if (!js_flags.empty()) v8::V8::SetFlagsFromString(js_flags.c_str()); // By enabling predictable mode, V8 won't post any background tasks. // By enabling GC, it makes it easier to chase use-after-free. static const char kAdditionalV8Flags[] = "--predictable --expose-gc"; v8::V8::SetFlagsFromString(kAdditionalV8Flags); v8::V8::Initialize(); return platform; } } // namespace #ifdef V8_USE_EXTERNAL_STARTUP_DATA std::unique_ptr InitializeV8ForPDFiumWithStartupData( const std::string& exe_path, const std::string& js_flags, const std::string& bin_dir, v8::StartupData* snapshot_blob) { std::unique_ptr platform = InitializeV8Common(exe_path, js_flags); if (snapshot_blob) { if (!GetExternalData(exe_path, bin_dir, "snapshot_blob.bin", snapshot_blob)) return nullptr; v8::V8::SetSnapshotDataBlob(snapshot_blob); } return platform; } #else // V8_USE_EXTERNAL_STARTUP_DATA std::unique_ptr InitializeV8ForPDFium( const std::string& exe_path, const std::string& js_flags) { return InitializeV8Common(exe_path, js_flags); } #endif // V8_USE_EXTERNAL_STARTUP_DATA void ShutdownV8ForPDFium() { #ifdef PDF_ENABLE_XFA cppgc::ShutdownProcess(); #endif v8::V8::Dispose(); v8::V8::DisposePlatform(); }