summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/all.gyp3
-rw-r--r--testing/libfuzzer/BUILD.gn51
-rw-r--r--testing/libfuzzer/fuzzers.gyp65
-rw-r--r--testing/libfuzzer/pdf_fm2js_fuzzer.cc25
-rw-r--r--testing/libfuzzer/pdf_xml_fuzzer.cc76
-rw-r--r--testing/libfuzzer/unittest_main.cc41
6 files changed, 260 insertions, 1 deletions
diff --git a/build/all.gyp b/build/all.gyp
index 7e2ea613ff..47097e39b4 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -10,7 +10,8 @@
'dependencies': [
'../pdfium.gyp:*',
'../samples/samples.gyp:*',
+ '../testing/libfuzzer/fuzzers.gyp:*',
],
}
]
-} \ No newline at end of file
+}
diff --git a/testing/libfuzzer/BUILD.gn b/testing/libfuzzer/BUILD.gn
new file mode 100644
index 0000000000..46cf0589d3
--- /dev/null
+++ b/testing/libfuzzer/BUILD.gn
@@ -0,0 +1,51 @@
+# Copyright 2016 The PDFium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("../../pdfium.gni")
+
+config("libfuzzer_config") {
+ defines = [
+ "PNG_PREFIX",
+ "PNGPREFIX_H",
+ "PNG_USE_READ_MACROS",
+ ]
+ include_dirs = [ "../.." ]
+ if (pdf_enable_v8) {
+ defines += [ "PDF_ENABLE_V8" ]
+ }
+ if (pdf_enable_xfa) {
+ defines += [ "PDF_ENABLE_XFA" ]
+ }
+}
+
+if (pdf_enable_xfa) {
+ source_set("pdf_fm2js_fuzzer") {
+ testonly = true
+ sources = [
+ "pdf_fm2js_fuzzer.cc",
+ ]
+ deps = [
+ "//third_party/pdfium:pdfium",
+ ]
+ configs -= [ "//build/config/compiler:chromium_code" ]
+ configs += [
+ "//build/config/compiler:no_chromium_code",
+ ":libfuzzer_config",
+ ]
+ }
+ source_set("pdf_xml_fuzzer") {
+ testonly = true
+ sources = [
+ "pdf_xml_fuzzer.cc",
+ ]
+ deps = [
+ "//third_party/pdfium:pdfium",
+ ]
+ configs -= [ "//build/config/compiler:chromium_code" ]
+ configs += [
+ "//build/config/compiler:no_chromium_code",
+ ":libfuzzer_config",
+ ]
+ }
+}
diff --git a/testing/libfuzzer/fuzzers.gyp b/testing/libfuzzer/fuzzers.gyp
new file mode 100644
index 0000000000..a3c0d452b5
--- /dev/null
+++ b/testing/libfuzzer/fuzzers.gyp
@@ -0,0 +1,65 @@
+# Copyright 2016 PDFium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'pdf_enable_v8%': 1,
+ 'pdf_enable_xfa%': 0, # Set to 1 in standalone builds by standalone.gypi.
+ },
+ 'target_defaults': {
+ 'defines' : [
+ 'PNG_PREFIX',
+ 'PNGPREFIX_H',
+ 'PNG_USE_READ_MACROS',
+ ],
+ 'include_dirs': [
+ # This is implicit in GN.
+ '<(DEPTH)',
+ ],
+ 'conditions': [
+ ['pdf_enable_v8==1', {
+ 'defines': [
+ 'PDF_ENABLE_V8',
+ ],
+ 'include_dirs': [
+ '<(DEPTH)/v8',
+ '<(DEPTH)/v8/include',
+ ],
+ }],
+ ['pdf_enable_xfa==1', {
+ 'defines': [
+ 'PDF_ENABLE_XFA',
+ ],
+ }],
+ ],
+ },
+ 'conditions': [
+ ['pdf_enable_xfa==1 and OS!="win"', {
+ 'targets': [
+ {
+ 'target_name': 'pdf_fm2js_fuzzer',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../pdfium.gyp:pdfium',
+ ],
+ 'sources': [
+ 'pdf_fm2js_fuzzer.cc',
+ 'unittest_main.cc',
+ ],
+ },
+ {
+ 'target_name': 'pdf_xml_fuzzer',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../pdfium.gyp:pdfium',
+ ],
+ 'sources': [
+ 'pdf_xml_fuzzer.cc',
+ 'unittest_main.cc',
+ ],
+ },
+ ],
+ }],
+ ]
+}
diff --git a/testing/libfuzzer/pdf_fm2js_fuzzer.cc b/testing/libfuzzer/pdf_fm2js_fuzzer.cc
new file mode 100644
index 0000000000..803ef7c843
--- /dev/null
+++ b/testing/libfuzzer/pdf_fm2js_fuzzer.cc
@@ -0,0 +1,25 @@
+// Copyright 2016 The PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cstddef>
+#include <cstdint>
+
+#include "core/include/fxcrt/fx_basic.h"
+#include "core/include/fxcrt/fx_string.h"
+#include "xfa/src/fxfa/src/fm2js/xfa_fm2js.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ if (size > std::numeric_limits<FX_STRSIZE>::max())
+ return 0;
+
+ CFX_WideString input = CFX_WideString::FromUTF8(
+ reinterpret_cast<const char*>(data), static_cast<FX_STRSIZE>(size));
+ CXFA_FMProgram program;
+ if (program.Init(input) || program.ParseProgram())
+ return 0;
+
+ CFX_WideTextBuf js;
+ program.TranslateProgram(js);
+ return 0;
+}
diff --git a/testing/libfuzzer/pdf_xml_fuzzer.cc b/testing/libfuzzer/pdf_xml_fuzzer.cc
new file mode 100644
index 0000000000..3eb1c8b5e5
--- /dev/null
+++ b/testing/libfuzzer/pdf_xml_fuzzer.cc
@@ -0,0 +1,76 @@
+// Copyright 2016 The PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <memory>
+
+#include "core/include/fxcrt/fx_basic.h"
+#include "core/include/fxcrt/fx_system.h"
+#include "xfa/src/foxitlib.h"
+#include "xfa/src/fxfa/src/common/xfa_common.h"
+#include "xfa/src/fxfa/src/parser/xfa_parser_imp.h"
+
+namespace {
+
+IFDE_XMLNode* XFA_FDEExtension_GetDocumentNode(
+ IFDE_XMLDoc* pXMLDoc,
+ FX_BOOL bVerifyWellFormness = FALSE) {
+ if (!pXMLDoc) {
+ return nullptr;
+ }
+ IFDE_XMLNode* pXMLFakeRoot = pXMLDoc->GetRoot();
+ for (IFDE_XMLNode* pXMLNode =
+ pXMLFakeRoot->GetNodeItem(IFDE_XMLNode::FirstChild);
+ pXMLNode; pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+ if (pXMLNode->GetType() == FDE_XMLNODE_Element) {
+ if (bVerifyWellFormness) {
+ for (IFDE_XMLNode* pNextNode =
+ pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling);
+ pNextNode;
+ pNextNode = pNextNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+ if (pNextNode->GetType() == FDE_XMLNODE_Element) {
+ return FALSE;
+ }
+ }
+ }
+ return pXMLNode;
+ }
+ }
+ return nullptr;
+}
+
+} // namespace
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ if (size > std::numeric_limits<FX_STRSIZE>::max())
+ return 0;
+
+ CFX_WideString input = CFX_WideString::FromUTF8(
+ reinterpret_cast<const char*>(data), static_cast<FX_STRSIZE>(size));
+ std::unique_ptr<IFX_Stream, ReleaseDeleter<IFX_Stream>> stream(
+ XFA_CreateWideTextRead(input));
+ if (!stream)
+ return 0;
+
+ std::unique_ptr<IFDE_XMLDoc> doc(IFDE_XMLDoc::Create());
+ if (!doc)
+ return 0;
+
+ std::unique_ptr<IFDE_XMLParser, ReleaseDeleter<IFDE_XMLParser>> parser(
+ new CXFA_XMLParser(doc->GetRoot(), stream.get()));
+ if (!parser)
+ return 0;
+
+ if (!doc->LoadXML(parser.release()))
+ return 0;
+
+ int32_t load_result = doc->DoLoad(nullptr);
+ if (load_result < 100)
+ return 0;
+
+ (void)XFA_FDEExtension_GetDocumentNode(doc.get());
+ return 0;
+}
diff --git a/testing/libfuzzer/unittest_main.cc b/testing/libfuzzer/unittest_main.cc
new file mode 100644
index 0000000000..f6b29e483f
--- /dev/null
+++ b/testing/libfuzzer/unittest_main.cc
@@ -0,0 +1,41 @@
+// Copyright 2015 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.
+
+// A simple unit-test style driver for libfuzzer tests.
+// Usage: <fuzzer_test> <file>...
+
+#include <fstream>
+#include <iostream>
+#include <iterator>
+#include <vector>
+
+// Libfuzzer API.
+extern "C" {
+// User function.
+int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size);
+// Initialization function.
+__attribute__((weak)) int LLVMFuzzerInitialize(int* argc, char*** argv);
+}
+
+std::vector<char> readFile(std::string path) {
+ std::ifstream in(path);
+ return std::vector<char>((std::istreambuf_iterator<char>(in)),
+ std::istreambuf_iterator<char>());
+}
+
+int main(int argc, char** argv) {
+ if (argc == 1) {
+ std::cerr << "Usage: " << argv[0] << " <file>..." << std::endl;
+ exit(1);
+ }
+
+ if (LLVMFuzzerInitialize)
+ LLVMFuzzerInitialize(&argc, &argv);
+
+ for (int i = 1; i < argc; ++i) {
+ std::cout << argv[i] << std::endl;
+ auto v = readFile(argv[i]);
+ LLVMFuzzerTestOneInput((const unsigned char*)v.data(), v.size());
+ }
+}