diff options
Diffstat (limited to 'testing/fuzzers')
28 files changed, 1076 insertions, 0 deletions
diff --git a/testing/fuzzers/BUILD.gn b/testing/fuzzers/BUILD.gn new file mode 100644 index 0000000000..59211b1758 --- /dev/null +++ b/testing/fuzzers/BUILD.gn @@ -0,0 +1,253 @@ +# 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("fuzzer_config") { + configs = [ "../..:pdfium_core_config" ] + + defines = [ + "PNG_PREFIX", + "PNG_USE_READ_MACROS", + ] + include_dirs = [ "../.." ] + if (pdf_enable_v8) { + defines += [ "PDF_ENABLE_V8" ] + } + if (pdf_enable_xfa) { + defines += [ "PDF_ENABLE_XFA" ] + } +} + +group("fuzzers") { + testonly = true + deps = [ + ":pdf_cmap_fuzzer_src", + ":pdf_codec_a85_fuzzer_src", + ":pdf_codec_fax_fuzzer_src", + ":pdf_codec_icc_fuzzer_src", + ":pdf_codec_jbig2_fuzzer_src", + ":pdf_codec_rle_fuzzer_src", + ":pdf_font_fuzzer_src", + ":pdf_hint_table_fuzzer_src", + ":pdf_jpx_fuzzer_src", + ":pdf_psengine_fuzzer_src", + ":pdf_streamparser_fuzzer_src", + ":pdf_xml_fuzzer_src", + ] + if (pdf_enable_xfa) { + deps += [ + ":pdf_bidi_fuzzer_src", + ":pdf_cfx_barcode_fuzzer_src", + ":pdf_codec_jpeg_fuzzer_src", + ":pdf_css_fuzzer_src", + ":pdf_fm2js_fuzzer_src", + ":pdf_formcalc_fuzzer_src", + ] + if (pdf_enable_xfa_bmp) { + deps += [ ":pdf_codec_bmp_fuzzer_src" ] + } + if (pdf_enable_xfa_gif) { + deps += [ + ":pdf_codec_gif_fuzzer_src", + ":pdf_lzw_fuzzer_src", + ] + } + if (pdf_enable_xfa_png) { + deps += [ ":pdf_codec_png_fuzzer_src" ] + } + if (pdf_enable_xfa_tiff) { + deps += [ ":pdf_codec_tiff_fuzzer_src" ] + } + } +} + +template("pdfium_fuzzer") { + source_set(target_name) { + sources = invoker.sources + [ "pdf_fuzzer_init.cc" ] + deps = [ + "../..:pdfium", + ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + testonly = true + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + "//build/config/compiler:no_chromium_code", + ":fuzzer_config", + ] + } +} + +if (pdf_enable_xfa) { + pdfium_fuzzer("pdf_bidi_fuzzer_src") { + sources = [ + "pdf_bidi_fuzzer.cc", + ] + } + + pdfium_fuzzer("pdf_cfx_barcode_fuzzer_src") { + sources = [ + "pdf_cfx_barcode_fuzzer.cc", + ] + } + + if (pdf_enable_xfa_bmp) { + pdfium_fuzzer("pdf_codec_bmp_fuzzer_src") { + sources = [ + "pdf_codec_bmp_fuzzer.cc", + "xfa_codec_fuzzer.h", + ] + deps = [ + "../../:test_support", + ] + } + } + + if (pdf_enable_xfa_gif) { + pdfium_fuzzer("pdf_codec_gif_fuzzer_src") { + sources = [ + "pdf_codec_gif_fuzzer.cc", + "xfa_codec_fuzzer.h", + ] + deps = [ + "../../:test_support", + ] + } + + pdfium_fuzzer("pdf_lzw_fuzzer_src") { + sources = [ + "pdf_lzw_fuzzer.cc", + ] + } + } + + pdfium_fuzzer("pdf_codec_jpeg_fuzzer_src") { + sources = [ + "pdf_codec_jpeg_fuzzer.cc", + "xfa_codec_fuzzer.h", + ] + deps = [ + "../../:test_support", + ] + } + + if (pdf_enable_xfa_png) { + pdfium_fuzzer("pdf_codec_png_fuzzer_src") { + sources = [ + "pdf_codec_png_fuzzer.cc", + "xfa_codec_fuzzer.h", + ] + deps = [ + "../../:test_support", + ] + } + } + + if (pdf_enable_xfa_tiff) { + pdfium_fuzzer("pdf_codec_tiff_fuzzer_src") { + sources = [ + "pdf_codec_tiff_fuzzer.cc", + "xfa_codec_fuzzer.h", + ] + deps = [ + "../../:test_support", + ] + } + } + + pdfium_fuzzer("pdf_css_fuzzer_src") { + sources = [ + "pdf_css_fuzzer.cc", + ] + } + + pdfium_fuzzer("pdf_fm2js_fuzzer_src") { + sources = [ + "pdf_fm2js_fuzzer.cc", + ] + } + + pdfium_fuzzer("pdf_formcalc_fuzzer_src") { + sources = [ + "pdf_formcalc_fuzzer.cc", + ] + } +} + +pdfium_fuzzer("pdf_cmap_fuzzer_src") { + sources = [ + "pdf_cmap_fuzzer.cc", + ] +} + +pdfium_fuzzer("pdf_codec_a85_fuzzer_src") { + sources = [ + "pdf_codec_a85_fuzzer.cc", + ] +} + +pdfium_fuzzer("pdf_codec_fax_fuzzer_src") { + sources = [ + "pdf_codec_fax_fuzzer.cc", + ] +} + +pdfium_fuzzer("pdf_codec_icc_fuzzer_src") { + deps = [ + "../../third_party/:lcms2", + ] + sources = [ + "pdf_codec_icc_fuzzer.cc", + ] +} + +pdfium_fuzzer("pdf_codec_jbig2_fuzzer_src") { + sources = [ + "pdf_codec_jbig2_fuzzer.cc", + ] +} + +pdfium_fuzzer("pdf_codec_rle_fuzzer_src") { + sources = [ + "pdf_codec_rle_fuzzer.cc", + ] +} + +pdfium_fuzzer("pdf_font_fuzzer_src") { + sources = [ + "pdf_font_fuzzer.cc", + ] +} + +pdfium_fuzzer("pdf_hint_table_fuzzer_src") { + sources = [ + "pdf_hint_table_fuzzer.cc", + ] +} + +pdfium_fuzzer("pdf_jpx_fuzzer_src") { + sources = [ + "pdf_jpx_fuzzer.cc", + ] +} + +pdfium_fuzzer("pdf_psengine_fuzzer_src") { + sources = [ + "pdf_psengine_fuzzer.cc", + ] +} + +pdfium_fuzzer("pdf_streamparser_fuzzer_src") { + sources = [ + "pdf_streamparser_fuzzer.cc", + ] +} + +pdfium_fuzzer("pdf_xml_fuzzer_src") { + sources = [ + "pdf_xml_fuzzer.cc", + ] +} diff --git a/testing/fuzzers/DEPS b/testing/fuzzers/DEPS new file mode 100644 index 0000000000..b1d034ed8c --- /dev/null +++ b/testing/fuzzers/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + '+xfa', +] diff --git a/testing/fuzzers/pdf_bidi_fuzzer.cc b/testing/fuzzers/pdf_bidi_fuzzer.cc new file mode 100644 index 0000000000..8e52688a10 --- /dev/null +++ b/testing/fuzzers/pdf_bidi_fuzzer.cc @@ -0,0 +1,36 @@ +// Copyright 2018 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 <cstdint> + +#include "core/fxcrt/fx_bidi.h" +#include "core/fxcrt/widestring.h" +#include "core/fxge/cfx_font.h" +#include "third_party/base/span.h" +#include "xfa/fgas/font/cfgas_fontmgr.h" +#include "xfa/fgas/font/cfgas_gefont.h" +#include "xfa/fgas/layout/cfx_rtfbreak.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + auto fontmgr = pdfium::MakeUnique<CFGAS_FontMgr>(); + + auto font = pdfium::MakeUnique<CFX_Font>(); + font->LoadSubst("Arial", true, 0, FXFONT_FW_NORMAL, 0, 0, 0); + assert(font); + + CFX_RTFBreak rtf_break(FX_LAYOUTSTYLE_ExpandTab); + rtf_break.SetLineBreakTolerance(1); + rtf_break.SetFont(CFGAS_GEFont::LoadFont(std::move(font), fontmgr.get())); + rtf_break.SetFontSize(12); + + WideString input = + WideString::FromUTF16LE(reinterpret_cast<const unsigned short*>(data), + size / sizeof(unsigned short)); + for (auto& ch : input) + rtf_break.AppendChar(ch); + + auto chars = rtf_break.GetCurrentLineForTesting()->m_LineChars; + FX_BidiLine(&chars, chars.size()); + return 0; +} diff --git a/testing/fuzzers/pdf_cfx_barcode_fuzzer.cc b/testing/fuzzers/pdf_cfx_barcode_fuzzer.cc new file mode 100644 index 0000000000..aaeebf3ace --- /dev/null +++ b/testing/fuzzers/pdf_cfx_barcode_fuzzer.cc @@ -0,0 +1,38 @@ +// Copyright 2017 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 <memory> + +#include "core/fxcrt/fx_string.h" +#include "xfa/fwl/cfx_barcode.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if (size < 2 * sizeof(wchar_t)) + return 0; + + BC_TYPE type = static_cast<BC_TYPE>(data[0] % (BC_DATAMATRIX + 1)); + + // Only used one byte, but align with wchar_t for string below. + data += sizeof(wchar_t); + size -= sizeof(wchar_t); + + auto barcode = CFX_Barcode::Create(type); + if (!barcode) + return 0; + + // TODO(tsepez): Setup more options from |data|. + barcode->SetModuleHeight(300); + barcode->SetModuleWidth(420); + barcode->SetHeight(298); + barcode->SetWidth(418); + + WideStringView content(reinterpret_cast<const wchar_t*>(data), + size / sizeof(wchar_t)); + + if (!barcode->Encode(content)) + return 0; + + // TODO(tsepez): Output to device. + return 0; +} diff --git a/testing/fuzzers/pdf_cmap_fuzzer.cc b/testing/fuzzers/pdf_cmap_fuzzer.cc new file mode 100644 index 0000000000..0c0ff11f36 --- /dev/null +++ b/testing/fuzzers/pdf_cmap_fuzzer.cc @@ -0,0 +1,14 @@ +// 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 <cstdint> + +#include "core/fpdfapi/font/cpdf_cmap.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/span.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + pdfium::MakeRetain<CPDF_CMap>()->LoadEmbedded(pdfium::make_span(data, size)); + return 0; +} diff --git a/testing/fuzzers/pdf_codec_a85_fuzzer.cc b/testing/fuzzers/pdf_codec_a85_fuzzer.cc new file mode 100644 index 0000000000..20bd792886 --- /dev/null +++ b/testing/fuzzers/pdf_codec_a85_fuzzer.cc @@ -0,0 +1,18 @@ +// Copyright 2017 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 <cstdint> +#include <memory> + +#include "core/fxcodec/codec/ccodec_basicmodule.h" +#include "core/fxcrt/fx_memory.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + uint8_t* dest_buf = nullptr; + uint32_t dest_size = 0; + CCodec_BasicModule encoder_module; + encoder_module.A85Encode(data, size, &dest_buf, &dest_size); + FX_Free(dest_buf); + return 0; +} diff --git a/testing/fuzzers/pdf_codec_bmp_fuzzer.cc b/testing/fuzzers/pdf_codec_bmp_fuzzer.cc new file mode 100644 index 0000000000..71f9150f5c --- /dev/null +++ b/testing/fuzzers/pdf_codec_bmp_fuzzer.cc @@ -0,0 +1,9 @@ +// 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 "testing/fuzzers/xfa_codec_fuzzer.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + return XFACodecFuzzer::Fuzz(data, size, FXCODEC_IMAGE_BMP); +} diff --git a/testing/fuzzers/pdf_codec_fax_fuzzer.cc b/testing/fuzzers/pdf_codec_fax_fuzzer.cc new file mode 100644 index 0000000000..f6cc1e7200 --- /dev/null +++ b/testing/fuzzers/pdf_codec_fax_fuzzer.cc @@ -0,0 +1,43 @@ +// 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 <cstdint> +#include <memory> + +#include "core/fxcodec/codec/ccodec_faxmodule.h" +#include "core/fxcodec/codec/ccodec_scanlinedecoder.h" + +static int GetInteger(const uint8_t* data) { + return data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + const int kParameterSize = 21; + if (size < kParameterSize) + return 0; + + int width = GetInteger(data); + int height = GetInteger(data + 4); + int K = GetInteger(data + 8); + int Columns = GetInteger(data + 12); + int Rows = GetInteger(data + 16); + bool EndOfLine = !(data[20] & 0x01); + bool ByteAlign = !(data[20] & 0x02); + bool BlackIs1 = !(data[20] & 0x04); + data += kParameterSize; + size -= kParameterSize; + + CCodec_FaxModule fax_module; + std::unique_ptr<CCodec_ScanlineDecoder> decoder( + fax_module.CreateDecoder(data, size, width, height, K, EndOfLine, + ByteAlign, BlackIs1, Columns, Rows)); + + if (decoder) { + int line = 0; + while (decoder->GetScanline(line)) + line++; + } + + return 0; +} diff --git a/testing/fuzzers/pdf_codec_gif_fuzzer.cc b/testing/fuzzers/pdf_codec_gif_fuzzer.cc new file mode 100644 index 0000000000..69129e7068 --- /dev/null +++ b/testing/fuzzers/pdf_codec_gif_fuzzer.cc @@ -0,0 +1,9 @@ +// 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 "testing/fuzzers/xfa_codec_fuzzer.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + return XFACodecFuzzer::Fuzz(data, size, FXCODEC_IMAGE_GIF); +} diff --git a/testing/fuzzers/pdf_codec_icc_fuzzer.cc b/testing/fuzzers/pdf_codec_icc_fuzzer.cc new file mode 100644 index 0000000000..7021017953 --- /dev/null +++ b/testing/fuzzers/pdf_codec_icc_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 <cstdint> + +#include "core/fxcodec/codec/ccodec_iccmodule.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + CCodec_IccModule icc_module; + uint32_t nComponent = 0; + std::unique_ptr<CLcmsCmm> transform = + icc_module.CreateTransform_sRGB(data, size, &nComponent); + + if (transform) { + float src[4]; + float dst[4]; + for (int i = 0; i < 4; i++) + src[i] = 0.5f; + icc_module.SetComponents(nComponent); + icc_module.Translate(transform.get(), src, dst); + } + + return 0; +} diff --git a/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc b/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc new file mode 100644 index 0000000000..7b8e2aac33 --- /dev/null +++ b/testing/fuzzers/pdf_codec_jbig2_fuzzer.cc @@ -0,0 +1,59 @@ +// 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 <cstdint> + +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fpdfapi/parser/cpdf_stream_acc.h" +#include "core/fxcodec/JBig2_DocumentContext.h" +#include "core/fxcodec/codec/ccodec_jbig2module.h" +#include "core/fxcodec/jbig2/JBig2_Context.h" +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxge/dib/cfx_dibitmap.h" +#include "core/fxge/fx_dib.h" +#include "third_party/base/ptr_util.h" + +static uint32_t GetInteger(const uint8_t* data) { + return data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + const size_t kParameterSize = 8; + if (size < kParameterSize) + return 0; + + uint32_t width = GetInteger(data); + uint32_t height = GetInteger(data + 4); + size -= kParameterSize; + data += kParameterSize; + + static constexpr uint32_t kMemLimit = 512000000; // 512 MB + static constexpr uint32_t k1bppRgbComponents = 4; // From CFX_DIBitmap impl. + FX_SAFE_UINT32 mem = width; + mem *= height; + mem *= k1bppRgbComponents; + if (!mem.IsValid() || mem.ValueOrDie() > kMemLimit) + return 0; + + auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>(); + if (!bitmap->Create(width, height, FXDIB_1bppRgb)) + return 0; + + auto stream = pdfium::MakeUnique<CPDF_Stream>(); + stream->AsStream()->SetData(data, size); + + auto src_stream = pdfium::MakeRetain<CPDF_StreamAcc>(stream->AsStream()); + src_stream->LoadAllDataRaw(); + + CCodec_Jbig2Module module; + CCodec_Jbig2Context jbig2_context; + std::unique_ptr<JBig2_DocumentContext> document_context; + FXCODEC_STATUS status = module.StartDecode( + &jbig2_context, &document_context, width, height, src_stream, nullptr, + bitmap->GetBuffer(), bitmap->GetPitch(), nullptr); + + while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) + status = module.ContinueDecode(&jbig2_context, nullptr); + return 0; +} diff --git a/testing/fuzzers/pdf_codec_jpeg_fuzzer.cc b/testing/fuzzers/pdf_codec_jpeg_fuzzer.cc new file mode 100644 index 0000000000..eaa0889e3c --- /dev/null +++ b/testing/fuzzers/pdf_codec_jpeg_fuzzer.cc @@ -0,0 +1,9 @@ +// 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 "testing/fuzzers/xfa_codec_fuzzer.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + return XFACodecFuzzer::Fuzz(data, size, FXCODEC_IMAGE_JPG); +} diff --git a/testing/fuzzers/pdf_codec_png_fuzzer.cc b/testing/fuzzers/pdf_codec_png_fuzzer.cc new file mode 100644 index 0000000000..61a65748fe --- /dev/null +++ b/testing/fuzzers/pdf_codec_png_fuzzer.cc @@ -0,0 +1,9 @@ +// 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 "testing/fuzzers/xfa_codec_fuzzer.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + return XFACodecFuzzer::Fuzz(data, size, FXCODEC_IMAGE_PNG); +} diff --git a/testing/fuzzers/pdf_codec_rle_fuzzer.cc b/testing/fuzzers/pdf_codec_rle_fuzzer.cc new file mode 100644 index 0000000000..c86671e5f4 --- /dev/null +++ b/testing/fuzzers/pdf_codec_rle_fuzzer.cc @@ -0,0 +1,18 @@ +// Copyright 2017 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 <cstdint> +#include <memory> + +#include "core/fxcodec/codec/ccodec_basicmodule.h" +#include "core/fxcrt/fx_memory.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + uint8_t* dest_buf = nullptr; + uint32_t dest_size = 0; + CCodec_BasicModule encoder_module; + encoder_module.RunLengthEncode(data, size, &dest_buf, &dest_size); + FX_Free(dest_buf); + return 0; +} diff --git a/testing/fuzzers/pdf_codec_tiff_fuzzer.cc b/testing/fuzzers/pdf_codec_tiff_fuzzer.cc new file mode 100644 index 0000000000..187c311fc7 --- /dev/null +++ b/testing/fuzzers/pdf_codec_tiff_fuzzer.cc @@ -0,0 +1,9 @@ +// 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 "testing/fuzzers/xfa_codec_fuzzer.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + return XFACodecFuzzer::Fuzz(data, size, FXCODEC_IMAGE_TIFF); +} diff --git a/testing/fuzzers/pdf_css_fuzzer.cc b/testing/fuzzers/pdf_css_fuzzer.cc new file mode 100644 index 0000000000..4f2f410aa3 --- /dev/null +++ b/testing/fuzzers/pdf_css_fuzzer.cc @@ -0,0 +1,27 @@ +// 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 <memory> + +#include "core/fxcrt/css/cfx_css.h" +#include "core/fxcrt/css/cfx_csssyntaxparser.h" +#include "core/fxcrt/fx_string.h" +#include "core/fxcrt/retain_ptr.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + WideString input = + WideString::FromUTF8(ByteStringView(data, static_cast<size_t>(size))); + + // If we convert the input into an empty string bail out. + if (input.GetLength() == 0) + return 0; + + CFX_CSSSyntaxParser parser(input.c_str(), input.GetLength()); + CFX_CSSSyntaxStatus status; + do { + status = parser.DoSyntaxParse(); + } while (status != CFX_CSSSyntaxStatus::Error && + status != CFX_CSSSyntaxStatus::EOS); + return 0; +} diff --git a/testing/fuzzers/pdf_fm2js_fuzzer.cc b/testing/fuzzers/pdf_fm2js_fuzzer.cc new file mode 100644 index 0000000000..2541dfbcc8 --- /dev/null +++ b/testing/fuzzers/pdf_fm2js_fuzzer.cc @@ -0,0 +1,23 @@ +// 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/fxcrt/cfx_widetextbuf.h" +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxcrt/fx_string.h" +#include "fxjs/cfxjse_formcalc_context.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FX_SAFE_SIZE_T safe_size = size; + if (!safe_size.IsValid()) + return 0; + + CFX_WideTextBuf js; + WideString input = + WideString::FromUTF8(ByteStringView(data, safe_size.ValueOrDie())); + CFXJSE_FormCalcContext::Translate(input.AsStringView(), &js); + return 0; +} diff --git a/testing/fuzzers/pdf_font_fuzzer.cc b/testing/fuzzers/pdf_font_fuzzer.cc new file mode 100644 index 0000000000..7c596307f0 --- /dev/null +++ b/testing/fuzzers/pdf_font_fuzzer.cc @@ -0,0 +1,31 @@ +// Copyright 2017 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 <cstring> +#include <memory> + +#include "public/cpp/fpdf_scopers.h" +#include "public/fpdf_edit.h" +#include "public/fpdfview.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if (size < 2) + return 0; + + ScopedFPDFDocument doc(FPDF_CreateNewDocument()); + ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 612, 792)); + int font_type = data[0]; + FPDF_BOOL cid = data[1]; + data += 2; + size -= 2; + ScopedFPDFFont font(FPDFText_LoadFont(doc.get(), data, size, font_type, cid)); + if (!font) + return 0; + + FPDF_PAGEOBJECT text_object = + FPDFPageObj_CreateTextObj(doc.get(), font.get(), 12.0f); + FPDFPage_InsertObject(page.get(), text_object); + FPDFPage_GenerateContent(page.get()); + return 0; +} diff --git a/testing/fuzzers/pdf_formcalc_fuzzer.cc b/testing/fuzzers/pdf_formcalc_fuzzer.cc new file mode 100644 index 0000000000..08e22bb247 --- /dev/null +++ b/testing/fuzzers/pdf_formcalc_fuzzer.cc @@ -0,0 +1,16 @@ +// Copyright 2017 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 "core/fxcrt/cfx_widetextbuf.h" +#include "core/fxcrt/fx_string.h" +#include "xfa/fxfa/fm2js/cxfa_fmparser.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + WideString input = WideString::FromUTF8(ByteStringView(data, size)); + + CXFA_FMParser parser(input.AsStringView()); + parser.Parse(); + + return 0; +} diff --git a/testing/fuzzers/pdf_fuzzer_init.cc b/testing/fuzzers/pdf_fuzzer_init.cc new file mode 100644 index 0000000000..4b9790c3f8 --- /dev/null +++ b/testing/fuzzers/pdf_fuzzer_init.cc @@ -0,0 +1,21 @@ +// Copyright 2017 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 <string.h> + +#include "public/fpdfview.h" + +// Initialize the library once for all runs of the fuzzer. +struct TestCase { + TestCase() { + memset(&config, '\0', sizeof(config)); + config.version = 2; + config.m_pUserFontPaths = nullptr; + config.m_pIsolate = nullptr; + config.m_v8EmbedderSlot = 0; + FPDF_InitLibraryWithConfig(&config); + } + FPDF_LIBRARY_CONFIG config; +}; +static TestCase* testCase = new TestCase(); diff --git a/testing/fuzzers/pdf_hint_table_fuzzer.cc b/testing/fuzzers/pdf_hint_table_fuzzer.cc new file mode 100644 index 0000000000..50ca5cd693 --- /dev/null +++ b/testing/fuzzers/pdf_hint_table_fuzzer.cc @@ -0,0 +1,93 @@ +// 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 <cstdint> + +#include "core/fpdfapi/parser/cpdf_array.h" +#include "core/fpdfapi/parser/cpdf_boolean.h" +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_hint_tables.h" +#include "core/fpdfapi/parser/cpdf_linearized_header.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fxcrt/cfx_bitstream.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/span.h" + +int32_t GetData(const int32_t** data32, const uint8_t** data, size_t* size) { + const int32_t* ret = *data32; + ++(*data32); + *data += 4; + *size -= 4; + return *ret; +} + +class HintTableForFuzzing : public CPDF_HintTables { + public: + HintTableForFuzzing(CPDF_LinearizedHeader* pLinearized, + int shared_hint_table_offset) + : CPDF_HintTables(nullptr, pLinearized), + shared_hint_table_offset_(shared_hint_table_offset) {} + ~HintTableForFuzzing() {} + + void Fuzz(const uint8_t* data, size_t size) { + if (shared_hint_table_offset_ <= 0) + return; + + if (size < static_cast<size_t>(shared_hint_table_offset_)) + return; + + CFX_BitStream bs(pdfium::make_span(data, size)); + if (!ReadPageHintTable(&bs)) + return; + ReadSharedObjHintTable(&bs, shared_hint_table_offset_); + } + + private: + int shared_hint_table_offset_; +}; + +class FakeLinearized : public CPDF_LinearizedHeader { + public: + explicit FakeLinearized(CPDF_Dictionary* linearized_dict) + : CPDF_LinearizedHeader(linearized_dict, 0) {} +}; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // Need 28 bytes for |linearized_dict|. + // The header section of page offset hint table is 36 bytes. + // The header section of shared object hint table is 24 bytes. + if (size < 28 + 36 + 24) + return 0; + + const int32_t* data32 = reinterpret_cast<const int32_t*>(data); + + auto linearized_dict = pdfium::MakeUnique<CPDF_Dictionary>(); + // Set initial value. + linearized_dict->SetNewFor<CPDF_Boolean>("Linearized", true); + // Set first page end offset + linearized_dict->SetNewFor<CPDF_Number>("E", GetData(&data32, &data, &size)); + // Set page count + linearized_dict->SetNewFor<CPDF_Number>("N", GetData(&data32, &data, &size)); + // Set first page obj num + linearized_dict->SetNewFor<CPDF_Number>("O", GetData(&data32, &data, &size)); + // Set first page no + linearized_dict->SetNewFor<CPDF_Number>("P", GetData(&data32, &data, &size)); + + auto hint_info = pdfium::MakeUnique<CPDF_Array>(); + // Add primary hint stream offset + hint_info->AddNew<CPDF_Number>(GetData(&data32, &data, &size)); + // Add primary hint stream size + hint_info->AddNew<CPDF_Number>(GetData(&data32, &data, &size)); + // Set hint stream info. + linearized_dict->SetFor("H", std::move(hint_info)); + + const int shared_hint_table_offset = GetData(&data32, &data, &size); + + { + FakeLinearized linearized(linearized_dict.get()); + HintTableForFuzzing hint_table(&linearized, shared_hint_table_offset); + hint_table.Fuzz(data, size); + } + return 0; +} diff --git a/testing/fuzzers/pdf_jpx_fuzzer.cc b/testing/fuzzers/pdf_jpx_fuzzer.cc new file mode 100644 index 0000000000..da65bc2d9a --- /dev/null +++ b/testing/fuzzers/pdf_jpx_fuzzer.cc @@ -0,0 +1,57 @@ +// 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 <cstdint> +#include <memory> +#include <vector> + +#include "core/fxcodec/codec/ccodec_jpxmodule.h" +#include "core/fxcodec/codec/cjpx_decoder.h" +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxge/dib/cfx_dibitmap.h" +#include "core/fxge/fx_dib.h" + +CCodec_JpxModule g_module; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + std::unique_ptr<CJPX_Decoder> decoder = + g_module.CreateDecoder(data, size, nullptr); + if (!decoder) + return 0; + + uint32_t width; + uint32_t height; + uint32_t components; + g_module.GetImageInfo(decoder.get(), &width, &height, &components); + + static constexpr uint32_t kMemLimit = 1024 * 1024 * 1024; // 1 GB. + FX_SAFE_UINT32 mem = width; + mem *= height; + mem *= components; + if (!mem.IsValid() || mem.ValueOrDie() > kMemLimit) + return 0; + + FXDIB_Format format; + if (components == 1) { + format = FXDIB_8bppRgb; + } else if (components <= 3) { + format = FXDIB_Rgb; + } else if (components == 4) { + format = FXDIB_Rgb32; + } else { + width = (width * components + 2) / 3; + format = FXDIB_Rgb; + } + auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>(); + if (!bitmap->Create(width, height, format)) + return 0; + + std::vector<uint8_t> output_offsets(components); + for (uint32_t i = 0; i < components; ++i) + output_offsets[i] = i; + + g_module.Decode(decoder.get(), bitmap->GetBuffer(), bitmap->GetPitch(), + output_offsets); + return 0; +} diff --git a/testing/fuzzers/pdf_lzw_fuzzer.cc b/testing/fuzzers/pdf_lzw_fuzzer.cc new file mode 100644 index 0000000000..7e10d2a1ee --- /dev/null +++ b/testing/fuzzers/pdf_lzw_fuzzer.cc @@ -0,0 +1,58 @@ +// Copyright 2017 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 <vector> + +#include "core/fxcodec/gif/cfx_lzwdecompressor.h" +#include "third_party/base/numerics/safe_conversions.h" + +// Between 2x and 5x is a standard range for LZW according to a quick +// search of papers. Running up to 10x to catch any niche cases. +constexpr uint32_t kMinCompressionRatio = 2; +constexpr uint32_t kMaxCompressionRatio = 10; + +void LZWFuzz(const uint8_t* src_buf, + size_t src_size, + uint8_t color_exp, + uint8_t code_exp) { + std::unique_ptr<CFX_LZWDecompressor> decompressor = + CFX_LZWDecompressor::Create(color_exp, code_exp); + if (!decompressor) + return; + + for (uint32_t compressions_ratio = kMinCompressionRatio; + compressions_ratio <= kMaxCompressionRatio; compressions_ratio++) { + std::vector<uint8_t> dest_buf(compressions_ratio * src_size); + // This cast should be safe since the caller is checking for overflow on + // the initial data. + uint32_t dest_size = static_cast<uint32_t>(dest_buf.size()); + if (CFX_GifDecodeStatus::InsufficientDestSize != + decompressor->Decode(const_cast<uint8_t*>(src_buf), src_size, + dest_buf.data(), &dest_size)) + return; + } +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // Need at least 3 bytes to do anything. + if (size < 3) + return 0; + + // Normally the GIF would provide the code and color sizes, instead, going + // to assume they are the first two bytes of data provided. + uint8_t color_exp = data[0]; + uint8_t code_exp = data[1]; + const uint8_t* lzw_data = data + 2; + uint32_t lzw_data_size = static_cast<uint32_t>(size - 2); + // Check that there isn't going to be an overflow in the destination buffer + // size. + if (lzw_data_size > + std::numeric_limits<uint32_t>::max() / kMaxCompressionRatio) { + return 0; + } + + LZWFuzz(lzw_data, lzw_data_size, color_exp, code_exp); + + return 0; +} diff --git a/testing/fuzzers/pdf_psengine_fuzzer.cc b/testing/fuzzers/pdf_psengine_fuzzer.cc new file mode 100644 index 0000000000..d72088d4e3 --- /dev/null +++ b/testing/fuzzers/pdf_psengine_fuzzer.cc @@ -0,0 +1,15 @@ +// 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 <cstdint> + +#include "core/fpdfapi/page/cpdf_psengine.h" +#include "third_party/base/span.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + CPDF_PSEngine engine; + if (engine.Parse(pdfium::make_span(data, size))) + engine.Execute(); + return 0; +} diff --git a/testing/fuzzers/pdf_streamparser_fuzzer.cc b/testing/fuzzers/pdf_streamparser_fuzzer.cc new file mode 100644 index 0000000000..4d9a368916 --- /dev/null +++ b/testing/fuzzers/pdf_streamparser_fuzzer.cc @@ -0,0 +1,19 @@ +// 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 <cstdint> +#include <memory> + +#include "core/fpdfapi/page/cpdf_streamparser.h" +#include "core/fpdfapi/parser/cpdf_object.h" +#include "third_party/base/span.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + CPDF_StreamParser parser(pdfium::make_span(data, size)); + while (std::unique_ptr<CPDF_Object> pObj = + parser.ReadNextObject(true, false, 0)) + continue; + + return 0; +} diff --git a/testing/fuzzers/pdf_xml_fuzzer.cc b/testing/fuzzers/pdf_xml_fuzzer.cc new file mode 100644 index 0000000000..a3c399f78d --- /dev/null +++ b/testing/fuzzers/pdf_xml_fuzzer.cc @@ -0,0 +1,36 @@ +// 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 <memory> + +#include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/xml/cfx_xmldocument.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlparser.h" +#include "third_party/base/ptr_util.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FX_SAFE_SIZE_T safe_size = size; + if (!safe_size.IsValid()) + return 0; + + auto stream = pdfium::MakeRetain<CFX_MemoryStream>(const_cast<uint8_t*>(data), + size, false); + + CFX_XMLParser parser(stream); + std::unique_ptr<CFX_XMLDocument> doc = parser.Parse(); + if (!doc || !doc->GetRoot()) + return 0; + + for (CFX_XMLNode* pXMLNode = doc->GetRoot()->GetFirstChild(); pXMLNode; + pXMLNode = pXMLNode->GetNextSibling()) { + if (pXMLNode->GetType() == FX_XMLNODE_Element) + break; + } + return 0; +} diff --git a/testing/fuzzers/unittest_main.cc b/testing/fuzzers/unittest_main.cc new file mode 100644 index 0000000000..f6b29e483f --- /dev/null +++ b/testing/fuzzers/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()); + } +} diff --git a/testing/fuzzers/xfa_codec_fuzzer.h b/testing/fuzzers/xfa_codec_fuzzer.h new file mode 100644 index 0000000000..bfc069a31d --- /dev/null +++ b/testing/fuzzers/xfa_codec_fuzzer.h @@ -0,0 +1,87 @@ +// 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. + +#ifndef TESTING_FUZZERS_XFA_CODEC_FUZZER_H_ +#define TESTING_FUZZERS_XFA_CODEC_FUZZER_H_ + +#include <memory> + +#include "core/fxcodec/codec/ccodec_progressivedecoder.h" +#include "core/fxcodec/fx_codec.h" +#include "core/fxge/dib/cfx_dibitmap.h" +#include "testing/fx_string_testhelpers.h" +#include "third_party/base/ptr_util.h" + +#ifdef PDF_ENABLE_XFA_BMP +#include "core/fxcodec/codec/ccodec_bmpmodule.h" +#endif // PDF_ENABLE_XFA_BMP + +#ifdef PDF_ENABLE_XFA_GIF +#include "core/fxcodec/codec/ccodec_gifmodule.h" +#endif // PDF_ENABLE_XFA_GIF + +#ifdef PDF_ENABLE_XFA_PNG +#include "core/fxcodec/codec/ccodec_pngmodule.h" +#endif // PDF_ENABLE_XFA_PNG + +#ifdef PDF_ENABLE_XFA_TIFF +#include "core/fxcodec/codec/ccodec_tiffmodule.h" +#endif // PDF_ENABLE_XFA_TIFF + +// Support up to 64 MB. This prevents trivial OOM when MSAN is on and +// time outs. +const int kXFACodecFuzzerPixelLimit = 64000000; + +class XFACodecFuzzer { + public: + static int Fuzz(const uint8_t* data, size_t size, FXCODEC_IMAGE_TYPE type) { + auto mgr = pdfium::MakeUnique<CCodec_ModuleMgr>(); +#ifdef PDF_ENABLE_XFA_BMP + mgr->SetBmpModule(pdfium::MakeUnique<CCodec_BmpModule>()); +#endif // PDF_ENABLE_XFA_BMP +#ifdef PDF_ENABLE_XFA_GIF + mgr->SetGifModule(pdfium::MakeUnique<CCodec_GifModule>()); +#endif // PDF_ENABLE_XFA_GIF +#ifdef PDF_ENABLE_XFA_PNG + mgr->SetPngModule(pdfium::MakeUnique<CCodec_PngModule>()); +#endif // PDF_ENABLE_XFA_PNG +#ifdef PDF_ENABLE_XFA_TIFF + mgr->SetTiffModule(pdfium::MakeUnique<CCodec_TiffModule>()); +#endif // PDF_ENABLE_XFA_TIFF + + std::unique_ptr<CCodec_ProgressiveDecoder> decoder = + mgr->CreateProgressiveDecoder(); + auto source = pdfium::MakeRetain<CFX_BufferSeekableReadStream>(data, size); + FXCODEC_STATUS status = decoder->LoadImageInfo(source, type, nullptr, true); + if (status != FXCODEC_STATUS_FRAME_READY) + return 0; + + // Skipping very large images, since they will take a long time and may lead + // to OOM. + FX_SAFE_UINT32 bitmap_size = decoder->GetHeight(); + bitmap_size *= decoder->GetWidth(); + bitmap_size *= 4; // From CFX_DIBitmap impl. + if (!bitmap_size.IsValid() || + bitmap_size.ValueOrDie() > kXFACodecFuzzerPixelLimit) { + return 0; + } + + auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>(); + bitmap->Create(decoder->GetWidth(), decoder->GetHeight(), FXDIB_Argb); + + size_t frames; + std::tie(status, frames) = decoder->GetFrames(); + if (status != FXCODEC_STATUS_DECODE_READY || frames == 0) + return 0; + + status = decoder->StartDecode(bitmap, 0, 0, bitmap->GetWidth(), + bitmap->GetHeight()); + while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) + status = decoder->ContinueDecode(); + + return 0; + } +}; + +#endif // TESTING_FUZZERS_XFA_CODEC_FUZZER_H_ |