Skip to content

Commit

Permalink
Add pdfium_xfa_lpm_fuzzer an LPM based fuzzer for PDFium
Browse files Browse the repository at this point in the history
Only include parts that generate a PDF file that loads an empty XFA doc.

Bug: 969811
Change-Id: Ifab808fd9f052fac80b7b86668f8e9278d0370de
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1659849
Commit-Queue: Jonathan Metzman <metzman@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Auto-Submit: Jonathan Metzman <metzman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#676954}
  • Loading branch information
jonathanmetzman authored and Commit Bot committed Jul 12, 2019
1 parent 21645bf commit 8322a75
Show file tree
Hide file tree
Showing 9 changed files with 320 additions and 0 deletions.
55 changes: 55 additions & 0 deletions pdf/pdfium/fuzzers/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import("//testing/libfuzzer/fuzzer_test.gni")
import("//testing/test.gni")
import("//third_party/pdfium/pdfium.gni")
import("//third_party/protobuf/proto_library.gni")

group("fuzzers") {
}
Expand Down Expand Up @@ -46,6 +47,7 @@ group("pdf_fuzzers") {
":pdf_formcalc_context_fuzzer",
":pdf_formcalc_fuzzer",
":pdfium_xfa_fuzzer",
":pdfium_xfa_lpm_fuzzer",
]
if (pdf_enable_xfa_bmp) {
deps += [ ":pdf_codec_bmp_fuzzer" ]
Expand Down Expand Up @@ -306,5 +308,58 @@ if (pdf_enable_v8) {
dict = "dicts/pdf.dict"
seed_corpus = "corpora/xfa"
}

static_library("proto_to_xfa") {
sources = [
"pdfium_xfa_lpm_fuzzer/proto_to_xfa.cc",
"pdfium_xfa_lpm_fuzzer/proto_to_xfa.h",
"pdfium_xfa_lpm_fuzzer/simple_xfa_pdf.cc",
"pdfium_xfa_lpm_fuzzer/simple_xfa_pdf.h",
]
deps = [
":xfa_proto",
"//base",
]
}

fuzzer_test("pdfium_xfa_lpm_fuzzer") {
sources = [
"pdfium_xfa_lpm_fuzzer/fuzzer.cc",
]
deps = [
":proto_to_xfa",
"//base",
"//third_party/libprotobuf-mutator",
"//third_party/pdfium",
"//third_party/pdfium/testing/fuzzers:fuzzer_init_public",
]
if (!is_component_build) {
deps +=
[ "//third_party/pdfium/testing/fuzzers:pdfium_xfa_lpm_fuzzer_src" ]
}
include_dirs = [ "//third_party/pdfium" ]

# Don't build the fuzzer while it isn't actually producing XFA.
# TODO(metzman): Remove this once the fuzzer actually fuzzes XFA.
additional_configs = [ "//testing/libfuzzer:no_clusterfuzz" ]
}

test("pdfium_xfa_lpm_unittest") {
sources = [
"pdfium_xfa_lpm_fuzzer/simple_xfa_pdf_unittest.cc",
]

deps = [
":proto_to_xfa",
"//base/test:run_all_unittests",
"//testing/gtest",
]
}
}
}

proto_library("xfa_proto") {
sources = [
"pdfium_xfa_lpm_fuzzer/xfa.proto",
]
}
3 changes: 3 additions & 0 deletions pdf/pdfium/fuzzers/DEPS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include_rules = [
"+third_party/pdfium/testing/fuzzers",
]
26 changes: 26 additions & 0 deletions pdf/pdfium/fuzzers/pdfium_xfa_lpm_fuzzer/fuzzer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2019 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.

#include <stdio.h>

#include "pdf/pdfium/fuzzers/pdfium_xfa_lpm_fuzzer/proto_to_xfa.h"
#include "pdf/pdfium/fuzzers/pdfium_xfa_lpm_fuzzer/simple_xfa_pdf.h"
#include "pdf/pdfium/fuzzers/pdfium_xfa_lpm_fuzzer/xfa.pb.h"
#include "testing/libfuzzer/proto/lpm_interface.h"
#include "third_party/pdfium/testing/fuzzers/pdfium_xfa_lpm_fuzz_stub.h"

namespace pdfium_xfa_lpm_fuzzer {

DEFINE_PROTO_FUZZER(const xfa_proto::Xfa& xfa) {
xfa_proto::ProtoToXfa proto_to_xfa;
std::string xfa_string = proto_to_xfa.Convert(xfa);
std::string pdf_string = CreateSimpleXfaPdf(xfa_string);
if (getenv("LPM_DUMP_NATIVE_INPUT")) {
for (auto c : pdf_string)
putc(c, stdout);
}
PdfiumXFALPMFuzzStub(pdf_string.c_str(), pdf_string.size());
}

} // namespace pdfium_xfa_lpm_fuzzer
17 changes: 17 additions & 0 deletions pdf/pdfium/fuzzers/pdfium_xfa_lpm_fuzzer/proto_to_xfa.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2019 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.

#include "pdf/pdfium/fuzzers/pdfium_xfa_lpm_fuzzer/proto_to_xfa.h"

namespace xfa_proto {

ProtoToXfa::ProtoToXfa() = default;
ProtoToXfa::~ProtoToXfa() = default;

std::string ProtoToXfa::Convert(const Xfa& xfa) {
// TODO(metzman): Actually return an XFA form rather than an empty string.
return "";
}

} // namespace xfa_proto
24 changes: 24 additions & 0 deletions pdf/pdfium/fuzzers/pdfium_xfa_lpm_fuzzer/proto_to_xfa.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2019 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.

#ifndef PDF_PDFIUM_FUZZERS_PDFIUM_XFA_LPM_FUZZER_PROTO_TO_XFA_H_
#define PDF_PDFIUM_FUZZERS_PDFIUM_XFA_LPM_FUZZER_PROTO_TO_XFA_H_

#include <string>

#include "pdf/pdfium/fuzzers/pdfium_xfa_lpm_fuzzer/xfa.pb.h"

namespace xfa_proto {

class ProtoToXfa {
public:
ProtoToXfa();
~ProtoToXfa();

std::string Convert(const Xfa& xfa);
};

} // namespace xfa_proto

#endif // PDF_PDFIUM_FUZZERS_PDFIUM_XFA_LPM_FUZZER_PROTO_TO_XFA_H_
89 changes: 89 additions & 0 deletions pdf/pdfium/fuzzers/pdfium_xfa_lpm_fuzzer/simple_xfa_pdf.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2019 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.

#include <string>
#include <vector>

#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "pdf/pdfium/fuzzers/pdfium_xfa_lpm_fuzzer/simple_xfa_pdf.h"

namespace pdfium_xfa_lpm_fuzzer {

namespace {

const char kSimplePdfTemplate[] = R"(%PDF-1.7
%
1 0 obj <<
/XFA 5 0 R
>>
endobj
2 0 obj <<
/Type /Pages
/Count 1
/Kids [3 0 R]
>>
endobj
3 0 obj <<
/Type /Page
/MediaBox [0 0 600 800]
/Parent 2 0 R
>>
endobj
4 0 obj <<
/Extensions <<
/ADBE <<
/BaseVersion /1.0
/ExtensionLevel 8
>>
>>
/Pages 2 0 R
/Type /Catalog
/AcroForm 1 0 R
/NeedsRendering true
>>
endobj
5 0 obj <<
/Length $1
>>
stream
$2
endstream
endobj
xref
6 0
0000000000 65535 f
0000000015 00000 n
0000000047 00000 n
0000000104 00000 n
0000000175 00000 n
0000000327 00000 n
trailer <<
/Size 6
/Root 4 0 R
>>
startxref
$3
%%EOF)";

} // namespace

std::string CreateSimpleXfaPdf(const std::string& xfa_string) {
// Add 1 for newline before endstream.
std::string xfa_stream_len = base::NumberToString(xfa_string.size() + 1);
// Each placeholder is two bytes. Two of them precede xref.
const size_t kPlaceholderSizes = 2 * 2;
static const size_t kCurrentXrefPosition =
std::string(kSimplePdfTemplate).find("xref");
std::string startxref =
base::NumberToString(kCurrentXrefPosition - kPlaceholderSizes +
xfa_string.size() + xfa_stream_len.size() + 1);
std::vector<std::string> replacements(
{xfa_stream_len, xfa_string, startxref});
return base::ReplaceStringPlaceholders(kSimplePdfTemplate, replacements,
nullptr);
}

} // namespace pdfium_xfa_lpm_fuzzer
16 changes: 16 additions & 0 deletions pdf/pdfium/fuzzers/pdfium_xfa_lpm_fuzzer/simple_xfa_pdf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2019 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.

#ifndef PDF_PDFIUM_FUZZERS_PDFIUM_XFA_LPM_FUZZER_SIMPLE_XFA_PDF_H_
#define PDF_PDFIUM_FUZZERS_PDFIUM_XFA_LPM_FUZZER_SIMPLE_XFA_PDF_H_

#include <string>

namespace pdfium_xfa_lpm_fuzzer {

std::string CreateSimpleXfaPdf(const std::string& xfa_string);

} // namespace pdfium_xfa_lpm_fuzzer

#endif // PDF_PDFIUM_FUZZERS_PDFIUM_XFA_LPM_FUZZER_SIMPLE_XFA_PDF_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2019 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.

#include "pdf/pdfium/fuzzers/pdfium_xfa_lpm_fuzzer/simple_xfa_pdf.h"

#include <string>
#include <utility>

#include "base/logging.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

const char kEmptyXfa[] = "";
const char kEmptyXfaPdf[] = R"(%PDF-1.7
%
1 0 obj <<
/XFA 5 0 R
>>
endobj
2 0 obj <<
/Type /Pages
/Count 1
/Kids [3 0 R]
>>
endobj
3 0 obj <<
/Type /Page
/MediaBox [0 0 600 800]
/Parent 2 0 R
>>
endobj
4 0 obj <<
/Extensions <<
/ADBE <<
/BaseVersion /1.0
/ExtensionLevel 8
>>
>>
/Pages 2 0 R
/Type /Catalog
/AcroForm 1 0 R
/NeedsRendering true
>>
endobj
5 0 obj <<
/Length 1
>>
stream
endstream
endobj
xref
6 0
0000000000 65535 f
0000000015 00000 n
0000000047 00000 n
0000000104 00000 n
0000000175 00000 n
0000000327 00000 n
trailer <<
/Size 6
/Root 4 0 R
>>
startxref
376
%%EOF)";

} // namespace

class SimpleXfaPdfTest
: public ::testing::TestWithParam<std::pair<std::string, std::string>> {};

TEST_P(SimpleXfaPdfTest, CheckTranslation) {
const std::pair<std::string, std::string>& param = GetParam();
ASSERT_EQ(param.second,
pdfium_xfa_lpm_fuzzer::CreateSimpleXfaPdf(param.first));
}

INSTANTIATE_TEST_SUITE_P(LpmFuzzer,
SimpleXfaPdfTest,
::testing::Values(std::make_pair(kEmptyXfa,
kEmptyXfaPdf)));
5 changes: 5 additions & 0 deletions pdf/pdfium/fuzzers/pdfium_xfa_lpm_fuzzer/xfa.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
syntax = "proto2";

package xfa_proto;

message Xfa {}

0 comments on commit 8322a75

Please sign in to comment.