1// Copyright 2015 PDFium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "testing/test_support.h" 6 7#include <stdio.h> 8#include <string.h> 9 10#include "core/fdrm/crypto/fx_crypt.h" 11#include "core/fxcrt/fx_memory.h" 12#include "core/fxcrt/fx_string.h" 13#include "testing/utils/path_service.h" 14 15#ifdef PDF_ENABLE_V8 16#include "v8/include/libplatform/libplatform.h" 17#include "v8/include/v8.h" 18#endif 19 20namespace { 21 22#ifdef PDF_ENABLE_V8 23#ifdef V8_USE_EXTERNAL_STARTUP_DATA 24// Returns the full path for an external V8 data file based on either 25// the currect exectuable path or an explicit override. 26std::string GetFullPathForSnapshotFile(const std::string& exe_path, 27 const std::string& bin_dir, 28 const std::string& filename) { 29 std::string result; 30 if (!bin_dir.empty()) { 31 result = bin_dir; 32 if (*bin_dir.rbegin() != PATH_SEPARATOR) { 33 result += PATH_SEPARATOR; 34 } 35 } else if (!exe_path.empty()) { 36 size_t last_separator = exe_path.rfind(PATH_SEPARATOR); 37 if (last_separator != std::string::npos) { 38 result = exe_path.substr(0, last_separator + 1); 39 } 40 } 41 result += filename; 42 return result; 43} 44 45bool GetExternalData(const std::string& exe_path, 46 const std::string& bin_dir, 47 const std::string& filename, 48 v8::StartupData* result_data) { 49 std::string full_path = 50 GetFullPathForSnapshotFile(exe_path, bin_dir, filename); 51 size_t data_length = 0; 52 std::unique_ptr<char, pdfium::FreeDeleter> data_buffer = 53 GetFileContents(full_path.c_str(), &data_length); 54 if (!data_buffer) 55 return false; 56 57 result_data->data = data_buffer.release(); 58 result_data->raw_size = data_length; 59 return true; 60} 61#endif // V8_USE_EXTERNAL_STARTUP_DATA 62 63void InitializeV8Common(const char* exe_path, v8::Platform** platform) { 64 v8::V8::InitializeICUDefaultLocation(exe_path); 65 66 *platform = v8::platform::CreateDefaultPlatform(); 67 v8::V8::InitializePlatform(*platform); 68 69 // By enabling predictable mode, V8 won't post any background tasks. 70 // By enabling GC, it makes it easier to chase use-after-free. 71 const char v8_flags[] = "--predictable --expose-gc"; 72 v8::V8::SetFlagsFromString(v8_flags, static_cast<int>(strlen(v8_flags))); 73 v8::V8::Initialize(); 74} 75#endif // PDF_ENABLE_V8 76 77} // namespace 78 79std::unique_ptr<char, pdfium::FreeDeleter> GetFileContents(const char* filename, 80 size_t* retlen) { 81 FILE* file = fopen(filename, "rb"); 82 if (!file) { 83 fprintf(stderr, "Failed to open: %s\n", filename); 84 return nullptr; 85 } 86 (void)fseek(file, 0, SEEK_END); 87 size_t file_length = ftell(file); 88 if (!file_length) { 89 return nullptr; 90 } 91 (void)fseek(file, 0, SEEK_SET); 92 std::unique_ptr<char, pdfium::FreeDeleter> buffer( 93 static_cast<char*>(malloc(file_length))); 94 if (!buffer) { 95 return nullptr; 96 } 97 size_t bytes_read = fread(buffer.get(), 1, file_length, file); 98 (void)fclose(file); 99 if (bytes_read != file_length) { 100 fprintf(stderr, "Failed to read: %s\n", filename); 101 return nullptr; 102 } 103 *retlen = bytes_read; 104 return buffer; 105} 106 107std::string GetPlatformString(FPDF_WIDESTRING wstr) { 108 WideString wide_string = 109 WideString::FromUTF16LE(wstr, WideString::WStringLength(wstr)); 110 return std::string(wide_string.UTF8Encode().c_str()); 111} 112 113std::wstring GetPlatformWString(FPDF_WIDESTRING wstr) { 114 if (!wstr) 115 return nullptr; 116 117 size_t characters = 0; 118 while (wstr[characters]) 119 ++characters; 120 121 std::wstring platform_string(characters, L'\0'); 122 for (size_t i = 0; i < characters + 1; ++i) { 123 const unsigned char* ptr = reinterpret_cast<const unsigned char*>(&wstr[i]); 124 platform_string[i] = ptr[0] + 256 * ptr[1]; 125 } 126 return platform_string; 127} 128 129std::vector<std::string> StringSplit(const std::string& str, char delimiter) { 130 std::vector<std::string> result; 131 size_t pos = 0; 132 while (1) { 133 size_t found = str.find(delimiter, pos); 134 if (found == std::string::npos) 135 break; 136 137 result.push_back(str.substr(pos, found - pos)); 138 pos = found + 1; 139 } 140 result.push_back(str.substr(pos)); 141 return result; 142} 143 144std::unique_ptr<unsigned short, pdfium::FreeDeleter> GetFPDFWideString( 145 const std::wstring& wstr) { 146 size_t length = sizeof(uint16_t) * (wstr.length() + 1); 147 std::unique_ptr<unsigned short, pdfium::FreeDeleter> result( 148 static_cast<unsigned short*>(malloc(length))); 149 char* ptr = reinterpret_cast<char*>(result.get()); 150 size_t i = 0; 151 for (wchar_t w : wstr) { 152 ptr[i++] = w & 0xff; 153 ptr[i++] = (w >> 8) & 0xff; 154 } 155 ptr[i++] = 0; 156 ptr[i] = 0; 157 return result; 158} 159 160std::string CryptToBase16(const uint8_t* digest) { 161 static char const zEncode[] = "0123456789abcdef"; 162 std::string ret; 163 ret.resize(32); 164 for (int i = 0, j = 0; i < 16; i++, j += 2) { 165 uint8_t a = digest[i]; 166 ret[j] = zEncode[(a >> 4) & 0xf]; 167 ret[j + 1] = zEncode[a & 0xf]; 168 } 169 return ret; 170} 171 172std::string GenerateMD5Base16(const uint8_t* data, uint32_t size) { 173 uint8_t digest[16]; 174 CRYPT_MD5Generate(data, size, digest); 175 return CryptToBase16(digest); 176} 177 178#ifdef PDF_ENABLE_V8 179#ifdef V8_USE_EXTERNAL_STARTUP_DATA 180bool InitializeV8ForPDFium(const std::string& exe_path, 181 const std::string& bin_dir, 182 v8::StartupData* natives_blob, 183 v8::StartupData* snapshot_blob, 184 v8::Platform** platform) { 185 InitializeV8Common(exe_path.c_str(), platform); 186 if (natives_blob && snapshot_blob) { 187 if (!GetExternalData(exe_path, bin_dir, "natives_blob.bin", natives_blob)) 188 return false; 189 if (!GetExternalData(exe_path, bin_dir, "snapshot_blob.bin", snapshot_blob)) 190 return false; 191 v8::V8::SetNativesDataBlob(natives_blob); 192 v8::V8::SetSnapshotDataBlob(snapshot_blob); 193 } 194 return true; 195} 196#else // V8_USE_EXTERNAL_STARTUP_DATA 197bool InitializeV8ForPDFium(const std::string& exe_path, 198 v8::Platform** platform) { 199 InitializeV8Common(exe_path.c_str(), platform); 200 return true; 201} 202#endif // V8_USE_EXTERNAL_STARTUP_DATA 203#endif // PDF_ENABLE_V8 204 205TestLoader::TestLoader(const char* pBuf, size_t len) 206 : m_pBuf(pBuf), m_Len(len) { 207} 208 209// static 210int TestLoader::GetBlock(void* param, 211 unsigned long pos, 212 unsigned char* pBuf, 213 unsigned long size) { 214 TestLoader* pLoader = static_cast<TestLoader*>(param); 215 if (pos + size < pos || pos + size > pLoader->m_Len) 216 return 0; 217 218 memcpy(pBuf, pLoader->m_pBuf + pos, size); 219 return 1; 220} 221