| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // This fuzzer is simplified & cleaned up pdfium/samples/pdfium_test.cc | 5 #include "pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h" |
| 6 | 6 |
| 7 #include <assert.h> | 7 class PDFiumFuzzer : public PDFiumFuzzerHelper { |
| 8 #include <limits.h> | 8 public: |
| 9 #include <stddef.h> | 9 PDFiumFuzzer() : PDFiumFuzzerHelper() {} |
| 10 #include <stdint.h> | 10 ~PDFiumFuzzer() override {} |
| 11 #include <stdio.h> | |
| 12 #include <stdlib.h> | |
| 13 #include <string.h> | |
| 14 | 11 |
| 15 #ifdef _MSC_VER | 12 int GetFormCallbackVersion() const override { return 1; } |
| 16 #include <Windows.h> | 13 }; |
| 17 #else | |
| 18 #include <unistd.h> | |
| 19 #endif | |
| 20 | 14 |
| 21 #include <list> | 15 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| 22 #include <memory> | 16 PDFiumFuzzer fuzzer; |
| 23 #include <sstream> | 17 fuzzer.RenderPdf(reinterpret_cast<const char*>(data), size); |
| 24 #include <string> | |
| 25 #include <utility> | |
| 26 #include <vector> | |
| 27 | |
| 28 #include "third_party/pdfium/public/cpp/fpdf_deleters.h" | |
| 29 #include "third_party/pdfium/public/fpdf_dataavail.h" | |
| 30 #include "third_party/pdfium/public/fpdf_ext.h" | |
| 31 #include "third_party/pdfium/public/fpdf_formfill.h" | |
| 32 #include "third_party/pdfium/public/fpdf_text.h" | |
| 33 #include "third_party/pdfium/public/fpdfview.h" | |
| 34 #include "third_party/pdfium/testing/test_support.h" | |
| 35 | |
| 36 #include "v8/include/v8.h" | |
| 37 | |
| 38 static int ExampleAppAlert(IPDF_JSPLATFORM*, | |
| 39 FPDF_WIDESTRING, | |
| 40 FPDF_WIDESTRING, | |
| 41 int, | |
| 42 int) { | |
| 43 return 0; | 18 return 0; |
| 44 } | 19 } |
| 45 | |
| 46 static void ExampleDocGotoPage(IPDF_JSPLATFORM*, int pageNumber) {} | |
| 47 | |
| 48 static void ExampleUnsupportedHandler(UNSUPPORT_INFO*, int type) {} | |
| 49 | |
| 50 FPDF_BOOL Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) { | |
| 51 return true; | |
| 52 } | |
| 53 | |
| 54 static void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {} | |
| 55 | |
| 56 static bool RenderPage(const FPDF_DOCUMENT& doc, | |
| 57 const FPDF_FORMHANDLE& form, | |
| 58 const int page_index) { | |
| 59 std::unique_ptr<void, FPDFPageDeleter> page(FPDF_LoadPage(doc, page_index)); | |
| 60 if (!page) | |
| 61 return false; | |
| 62 | |
| 63 std::unique_ptr<void, FPDFTextPageDeleter> text_page( | |
| 64 FPDFText_LoadPage(page.get())); | |
| 65 FORM_OnAfterLoadPage(page.get(), form); | |
| 66 FORM_DoPageAAction(page.get(), form, FPDFPAGE_AACTION_OPEN); | |
| 67 | |
| 68 const double scale = 1.0; | |
| 69 int width = static_cast<int>(FPDF_GetPageWidth(page.get()) * scale); | |
| 70 int height = static_cast<int>(FPDF_GetPageHeight(page.get()) * scale); | |
| 71 std::unique_ptr<void, FPDFBitmapDeleter> bitmap( | |
| 72 FPDFBitmap_Create(width, height, 0)); | |
| 73 if (bitmap) { | |
| 74 FPDFBitmap_FillRect(bitmap.get(), 0, 0, width, height, 0xFFFFFFFF); | |
| 75 FPDF_RenderPageBitmap(bitmap.get(), page.get(), 0, 0, width, height, 0, 0); | |
| 76 FPDF_FFLDraw(form, bitmap.get(), page.get(), 0, 0, width, height, 0, 0); | |
| 77 } | |
| 78 FORM_DoPageAAction(page.get(), form, FPDFPAGE_AACTION_CLOSE); | |
| 79 FORM_OnBeforeClosePage(page.get(), form); | |
| 80 return !!bitmap; | |
| 81 } | |
| 82 | |
| 83 static void RenderPdf(const char* pBuf, size_t len) { | |
| 84 IPDF_JSPLATFORM platform_callbacks; | |
| 85 memset(&platform_callbacks, '\0', sizeof(platform_callbacks)); | |
| 86 platform_callbacks.version = 3; | |
| 87 platform_callbacks.app_alert = ExampleAppAlert; | |
| 88 platform_callbacks.Doc_gotoPage = ExampleDocGotoPage; | |
| 89 | |
| 90 FPDF_FORMFILLINFO form_callbacks; | |
| 91 memset(&form_callbacks, '\0', sizeof(form_callbacks)); | |
| 92 form_callbacks.version = 1; | |
| 93 form_callbacks.m_pJsPlatform = &platform_callbacks; | |
| 94 | |
| 95 TestLoader loader(pBuf, len); | |
| 96 FPDF_FILEACCESS file_access; | |
| 97 memset(&file_access, '\0', sizeof(file_access)); | |
| 98 file_access.m_FileLen = static_cast<unsigned long>(len); | |
| 99 file_access.m_GetBlock = TestLoader::GetBlock; | |
| 100 file_access.m_Param = &loader; | |
| 101 | |
| 102 FX_FILEAVAIL file_avail; | |
| 103 memset(&file_avail, '\0', sizeof(file_avail)); | |
| 104 file_avail.version = 1; | |
| 105 file_avail.IsDataAvail = Is_Data_Avail; | |
| 106 | |
| 107 FX_DOWNLOADHINTS hints; | |
| 108 memset(&hints, '\0', sizeof(hints)); | |
| 109 hints.version = 1; | |
| 110 hints.AddSegment = Add_Segment; | |
| 111 | |
| 112 std::unique_ptr<void, FPDFAvailDeleter> pdf_avail( | |
| 113 FPDFAvail_Create(&file_avail, &file_access)); | |
| 114 | |
| 115 int nRet = PDF_DATA_NOTAVAIL; | |
| 116 bool bIsLinearized = false; | |
| 117 std::unique_ptr<void, FPDFDocumentDeleter> doc; | |
| 118 if (FPDFAvail_IsLinearized(pdf_avail.get()) == PDF_LINEARIZED) { | |
| 119 doc.reset(FPDFAvail_GetDocument(pdf_avail.get(), nullptr)); | |
| 120 if (doc) { | |
| 121 while (nRet == PDF_DATA_NOTAVAIL) | |
| 122 nRet = FPDFAvail_IsDocAvail(pdf_avail.get(), &hints); | |
| 123 | |
| 124 if (nRet == PDF_DATA_ERROR) | |
| 125 return; | |
| 126 | |
| 127 nRet = FPDFAvail_IsFormAvail(pdf_avail.get(), &hints); | |
| 128 if (nRet == PDF_FORM_ERROR || nRet == PDF_FORM_NOTAVAIL) | |
| 129 return; | |
| 130 | |
| 131 bIsLinearized = true; | |
| 132 } | |
| 133 } else { | |
| 134 doc.reset(FPDF_LoadCustomDocument(&file_access, nullptr)); | |
| 135 } | |
| 136 | |
| 137 if (!doc) | |
| 138 return; | |
| 139 | |
| 140 (void)FPDF_GetDocPermissions(doc.get()); | |
| 141 | |
| 142 std::unique_ptr<void, FPDFFormHandleDeleter> form( | |
| 143 FPDFDOC_InitFormFillEnvironment(doc.get(), &form_callbacks)); | |
| 144 FPDF_SetFormFieldHighlightColor(form.get(), 0, 0xFFE4DD); | |
| 145 FPDF_SetFormFieldHighlightAlpha(form.get(), 100); | |
| 146 FORM_DoDocumentJSAction(form.get()); | |
| 147 FORM_DoDocumentOpenAction(form.get()); | |
| 148 | |
| 149 int page_count = FPDF_GetPageCount(doc.get()); | |
| 150 for (int i = 0; i < page_count; ++i) { | |
| 151 if (bIsLinearized) { | |
| 152 nRet = PDF_DATA_NOTAVAIL; | |
| 153 while (nRet == PDF_DATA_NOTAVAIL) | |
| 154 nRet = FPDFAvail_IsPageAvail(pdf_avail.get(), i, &hints); | |
| 155 | |
| 156 if (nRet == PDF_DATA_ERROR) | |
| 157 return; | |
| 158 } | |
| 159 RenderPage(doc.get(), form.get(), i); | |
| 160 } | |
| 161 FORM_DoDocumentAAction(form.get(), FPDFDOC_AACTION_WC); | |
| 162 } | |
| 163 | |
| 164 std::string ProgramPath() { | |
| 165 #ifdef _MSC_VER | |
| 166 wchar_t wpath[MAX_PATH]; | |
| 167 char path[MAX_PATH]; | |
| 168 DWORD res = GetModuleFileName(NULL, wpath, MAX_PATH); | |
| 169 assert(res != 0); | |
| 170 wcstombs(path, wpath, MAX_PATH); | |
| 171 return std::string(path, res); | |
| 172 #else | |
| 173 char* path = new char[PATH_MAX + 1]; | |
| 174 assert(path); | |
| 175 ssize_t sz = readlink("/proc/self/exe", path, PATH_MAX); | |
| 176 assert(sz > 0); | |
| 177 std::string result(path, sz); | |
| 178 delete[] path; | |
| 179 return result; | |
| 180 #endif | |
| 181 } | |
| 182 | |
| 183 struct TestCase { | |
| 184 TestCase() { | |
| 185 InitializeV8ForPDFium(ProgramPath(), "", &natives_blob, &snapshot_blob, | |
| 186 &platform); | |
| 187 | |
| 188 memset(&config, '\0', sizeof(config)); | |
| 189 config.version = 2; | |
| 190 config.m_pUserFontPaths = nullptr; | |
| 191 config.m_pIsolate = nullptr; | |
| 192 config.m_v8EmbedderSlot = 0; | |
| 193 FPDF_InitLibraryWithConfig(&config); | |
| 194 | |
| 195 memset(&unsupport_info, '\0', sizeof(unsupport_info)); | |
| 196 unsupport_info.version = 1; | |
| 197 unsupport_info.FSDK_UnSupport_Handler = ExampleUnsupportedHandler; | |
| 198 FSDK_SetUnSpObjProcessHandler(&unsupport_info); | |
| 199 } | |
| 200 | |
| 201 v8::Platform* platform; | |
| 202 v8::StartupData natives_blob; | |
| 203 v8::StartupData snapshot_blob; | |
| 204 FPDF_LIBRARY_CONFIG config; | |
| 205 UNSUPPORT_INFO unsupport_info; | |
| 206 }; | |
| 207 | |
| 208 static TestCase* testCase = new TestCase(); | |
| 209 | |
| 210 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { | |
| 211 RenderPdf(reinterpret_cast<const char*>(data), size); | |
| 212 return 0; | |
| 213 } | |
| OLD | NEW |