summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOliver Chang <ochang@chromium.org>2016-02-16 11:42:07 -0800
committerOliver Chang <ochang@chromium.org>2016-02-16 11:42:07 -0800
commite67d21825c9fd4b805b9bea211e09225f3c2a85d (patch)
tree992a03762cedc49b2d1b60054be1a81ecb0d0f77
parent5f554133283d03b6b30bcecfcdc689cccf3799ec (diff)
downloadpdfium-e67d21825c9fd4b805b9bea211e09225f3c2a85d.tar.xz
Add initial libfuzzers for fm2js transpiling and XML parsing.
GN source_sets are added so that the fuzzers can be built from //testing/libfuzzer in a Chromium checkout. GYP targets are also added to make sure these always build properly on our waterfall. These don't actually build the proper libfuzzers, but build the target fuzz function with a driver main() since the actual build process is quite complicated. R=tsepez@chromium.org, thestig@chromium.org BUG=587126 Review URL: https://codereview.chromium.org/1701103002 .
-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());
+ }
+}