• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 namespace {
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.
GetFullPathForSnapshotFile(const std::string & exe_path,const std::string & bin_dir,const std::string & filename)26 std::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 
GetExternalData(const std::string & exe_path,const std::string & bin_dir,const std::string & filename,v8::StartupData * result_data)45 bool 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 
InitializeV8Common(const char * exe_path,v8::Platform ** platform)63 void 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 
GetFileContents(const char * filename,size_t * retlen)79 std::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 
GetPlatformString(FPDF_WIDESTRING wstr)107 std::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 
GetPlatformWString(FPDF_WIDESTRING wstr)113 std::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 
StringSplit(const std::string & str,char delimiter)129 std::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 
GetFPDFWideString(const std::wstring & wstr)144 std::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 
CryptToBase16(const uint8_t * digest)160 std::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 
GenerateMD5Base16(const uint8_t * data,uint32_t size)172 std::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
InitializeV8ForPDFium(const std::string & exe_path,const std::string & bin_dir,v8::StartupData * natives_blob,v8::StartupData * snapshot_blob,v8::Platform ** platform)180 bool 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
InitializeV8ForPDFium(const std::string & exe_path,v8::Platform ** platform)197 bool 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 
TestLoader(const char * pBuf,size_t len)205 TestLoader::TestLoader(const char* pBuf, size_t len)
206     : m_pBuf(pBuf), m_Len(len) {
207 }
208 
209 // static
GetBlock(void * param,unsigned long pos,unsigned char * pBuf,unsigned long size)210 int 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