Skip to content

Commit

Permalink
Add XFA pdfium fuzzer
Browse files Browse the repository at this point in the history
This CL updates the pdfium_fuzzer to also build in the needed XFA code.
The BUILD file is changed to only build pdfium_fuzzer if we're not
in XFA and build pdfium_xfa_fuzzer if we're in XFA.

Review-Url: https://codereview.chromium.org/2754103002
Cr-Commit-Position: refs/heads/master@{#459186}
  • Loading branch information
dj2 authored and Commit bot committed Mar 23, 2017
1 parent d36c05b commit 034ca93
Show file tree
Hide file tree
Showing 5 changed files with 335 additions and 203 deletions.
23 changes: 23 additions & 0 deletions pdf/pdfium/fuzzers/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ group("fuzzers") {
fuzzer_test("pdfium_fuzzer") {
sources = [
"pdfium_fuzzer.cc",
"pdfium_fuzzer_helper.cc",
"pdfium_fuzzer_helper.h",
]
deps = [
"//third_party/pdfium",
Expand All @@ -26,6 +28,7 @@ fuzzer_test("pdfium_fuzzer") {
"//v8:external_startup_data",
]
dict = "dicts/pdf.dict"
seed_corpus = "src/third_party/pdfium/test"
}

fuzzer_test("pdf_cmap_fuzzer") {
Expand Down Expand Up @@ -181,4 +184,24 @@ if (pdf_enable_xfa) {
]
dict = "dicts/pdf_xml.dict"
}

fuzzer_test("pdfium_xfa_fuzzer") {
sources = [
"pdfium_fuzzer_helper.cc",
"pdfium_fuzzer_helper.h",
"pdfium_xfa_fuzzer.cc",
]
deps = [
"//third_party/pdfium",
"//third_party/pdfium:test_support",
"//v8",
"//v8:v8_libplatform",
]
additional_configs = [
"//third_party/pdfium:pdfium_core_config",
"//v8:external_startup_data",
]
dict = "dicts/pdf.dict"
seed_corpus = "src/third_party/pdfium/test"
}
}
212 changes: 9 additions & 203 deletions pdf/pdfium/fuzzers/pdfium_fuzzer.cc
Original file line number Diff line number Diff line change
@@ -1,213 +1,19 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This fuzzer is simplified & cleaned up pdfium/samples/pdfium_test.cc
#include "pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h"

#include <assert.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
class PDFiumFuzzer : public PDFiumFuzzerHelper {
public:
PDFiumFuzzer() : PDFiumFuzzerHelper() {}
~PDFiumFuzzer() override {}

#ifdef _MSC_VER
#include <Windows.h>
#else
#include <unistd.h>
#endif

#include <list>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "third_party/pdfium/public/cpp/fpdf_deleters.h"
#include "third_party/pdfium/public/fpdf_dataavail.h"
#include "third_party/pdfium/public/fpdf_ext.h"
#include "third_party/pdfium/public/fpdf_formfill.h"
#include "third_party/pdfium/public/fpdf_text.h"
#include "third_party/pdfium/public/fpdfview.h"
#include "third_party/pdfium/testing/test_support.h"

#include "v8/include/v8.h"

static int ExampleAppAlert(IPDF_JSPLATFORM*,
FPDF_WIDESTRING,
FPDF_WIDESTRING,
int,
int) {
return 0;
}

static void ExampleDocGotoPage(IPDF_JSPLATFORM*, int pageNumber) {}

static void ExampleUnsupportedHandler(UNSUPPORT_INFO*, int type) {}

FPDF_BOOL Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) {
return true;
}

static void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {}

static bool RenderPage(const FPDF_DOCUMENT& doc,
const FPDF_FORMHANDLE& form,
const int page_index) {
std::unique_ptr<void, FPDFPageDeleter> page(FPDF_LoadPage(doc, page_index));
if (!page)
return false;

std::unique_ptr<void, FPDFTextPageDeleter> text_page(
FPDFText_LoadPage(page.get()));
FORM_OnAfterLoadPage(page.get(), form);
FORM_DoPageAAction(page.get(), form, FPDFPAGE_AACTION_OPEN);

const double scale = 1.0;
int width = static_cast<int>(FPDF_GetPageWidth(page.get()) * scale);
int height = static_cast<int>(FPDF_GetPageHeight(page.get()) * scale);
std::unique_ptr<void, FPDFBitmapDeleter> bitmap(
FPDFBitmap_Create(width, height, 0));
if (bitmap) {
FPDFBitmap_FillRect(bitmap.get(), 0, 0, width, height, 0xFFFFFFFF);
FPDF_RenderPageBitmap(bitmap.get(), page.get(), 0, 0, width, height, 0, 0);
FPDF_FFLDraw(form, bitmap.get(), page.get(), 0, 0, width, height, 0, 0);
}
FORM_DoPageAAction(page.get(), form, FPDFPAGE_AACTION_CLOSE);
FORM_OnBeforeClosePage(page.get(), form);
return !!bitmap;
}

static void RenderPdf(const char* pBuf, size_t len) {
IPDF_JSPLATFORM platform_callbacks;
memset(&platform_callbacks, '\0', sizeof(platform_callbacks));
platform_callbacks.version = 3;
platform_callbacks.app_alert = ExampleAppAlert;
platform_callbacks.Doc_gotoPage = ExampleDocGotoPage;

FPDF_FORMFILLINFO form_callbacks;
memset(&form_callbacks, '\0', sizeof(form_callbacks));
form_callbacks.version = 1;
form_callbacks.m_pJsPlatform = &platform_callbacks;

TestLoader loader(pBuf, 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_Param = &loader;

FX_FILEAVAIL file_avail;
memset(&file_avail, '\0', sizeof(file_avail));
file_avail.version = 1;
file_avail.IsDataAvail = Is_Data_Avail;

FX_DOWNLOADHINTS hints;
memset(&hints, '\0', sizeof(hints));
hints.version = 1;
hints.AddSegment = Add_Segment;

std::unique_ptr<void, FPDFAvailDeleter> pdf_avail(
FPDFAvail_Create(&file_avail, &file_access));

int nRet = PDF_DATA_NOTAVAIL;
bool bIsLinearized = false;
std::unique_ptr<void, FPDFDocumentDeleter> doc;
if (FPDFAvail_IsLinearized(pdf_avail.get()) == PDF_LINEARIZED) {
doc.reset(FPDFAvail_GetDocument(pdf_avail.get(), nullptr));
if (doc) {
while (nRet == PDF_DATA_NOTAVAIL)
nRet = FPDFAvail_IsDocAvail(pdf_avail.get(), &hints);

if (nRet == PDF_DATA_ERROR)
return;

nRet = FPDFAvail_IsFormAvail(pdf_avail.get(), &hints);
if (nRet == PDF_FORM_ERROR || nRet == PDF_FORM_NOTAVAIL)
return;

bIsLinearized = true;
}
} else {
doc.reset(FPDF_LoadCustomDocument(&file_access, nullptr));
}

if (!doc)
return;

(void)FPDF_GetDocPermissions(doc.get());

std::unique_ptr<void, FPDFFormHandleDeleter> form(
FPDFDOC_InitFormFillEnvironment(doc.get(), &form_callbacks));
FPDF_SetFormFieldHighlightColor(form.get(), 0, 0xFFE4DD);
FPDF_SetFormFieldHighlightAlpha(form.get(), 100);
FORM_DoDocumentJSAction(form.get());
FORM_DoDocumentOpenAction(form.get());

int page_count = FPDF_GetPageCount(doc.get());
for (int i = 0; i < page_count; ++i) {
if (bIsLinearized) {
nRet = PDF_DATA_NOTAVAIL;
while (nRet == PDF_DATA_NOTAVAIL)
nRet = FPDFAvail_IsPageAvail(pdf_avail.get(), i, &hints);

if (nRet == PDF_DATA_ERROR)
return;
}
RenderPage(doc.get(), form.get(), i);
}
FORM_DoDocumentAAction(form.get(), FPDFDOC_AACTION_WC);
}

std::string ProgramPath() {
#ifdef _MSC_VER
wchar_t wpath[MAX_PATH];
char path[MAX_PATH];
DWORD res = GetModuleFileName(NULL, wpath, MAX_PATH);
assert(res != 0);
wcstombs(path, wpath, MAX_PATH);
return std::string(path, res);
#else
char* path = new char[PATH_MAX + 1];
assert(path);
ssize_t sz = readlink("/proc/self/exe", path, PATH_MAX);
assert(sz > 0);
std::string result(path, sz);
delete[] path;
return result;
#endif
}

struct TestCase {
TestCase() {
InitializeV8ForPDFium(ProgramPath(), "", &natives_blob, &snapshot_blob,
&platform);

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);
}

v8::Platform* platform;
v8::StartupData natives_blob;
v8::StartupData snapshot_blob;
FPDF_LIBRARY_CONFIG config;
UNSUPPORT_INFO unsupport_info;
int GetFormCallbackVersion() const override { return 1; }
};

static TestCase* testCase = new TestCase();

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
RenderPdf(reinterpret_cast<const char*>(data), size);
PDFiumFuzzer fuzzer;
fuzzer.RenderPdf(reinterpret_cast<const char*>(data), size);
return 0;
}
Loading

0 comments on commit 034ca93

Please sign in to comment.