From 7996fe888cb98597cd1608af05fb59f45c837fc6 Mon Sep 17 00:00:00 2001 From: tsepez Date: Thu, 18 Aug 2016 14:37:07 -0700 Subject: Add llvm fuzzer for CPDF_PSEngine Put class definition into its own header file so fuzzer can find it. Fix a pair of div by 0s immediately hit by the fuzzer. Review-Url: https://codereview.chromium.org/2253193003 --- core/fpdfapi/fpdf_page/cpdf_psengine.h | 100 ++++++++++++++++++++++++++++++ core/fpdfapi/fpdf_page/fpdf_page_func.cpp | 95 +++------------------------- testing/libfuzzer/BUILD.gn | 15 +++++ testing/libfuzzer/pdf_psengine_fuzzer.cc | 14 +++++ 4 files changed, 137 insertions(+), 87 deletions(-) create mode 100644 core/fpdfapi/fpdf_page/cpdf_psengine.h create mode 100644 testing/libfuzzer/pdf_psengine_fuzzer.cc diff --git a/core/fpdfapi/fpdf_page/cpdf_psengine.h b/core/fpdfapi/fpdf_page/cpdf_psengine.h new file mode 100644 index 0000000000..fc8badbe6d --- /dev/null +++ b/core/fpdfapi/fpdf_page/cpdf_psengine.h @@ -0,0 +1,100 @@ +// 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. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FPDFAPI_FPDF_PAGE_CPDF_PSENGINE_H_ +#define CORE_FPDFAPI_FPDF_PAGE_CPDF_PSENGINE_H_ + +#include +#include + +#include "core/fxcrt/include/fx_system.h" + +class CPDF_PSEngine; +class CPDF_PSOP; +class CPDF_SimpleParser; + +enum PDF_PSOP { + PSOP_ADD, + PSOP_SUB, + PSOP_MUL, + PSOP_DIV, + PSOP_IDIV, + PSOP_MOD, + PSOP_NEG, + PSOP_ABS, + PSOP_CEILING, + PSOP_FLOOR, + PSOP_ROUND, + PSOP_TRUNCATE, + PSOP_SQRT, + PSOP_SIN, + PSOP_COS, + PSOP_ATAN, + PSOP_EXP, + PSOP_LN, + PSOP_LOG, + PSOP_CVI, + PSOP_CVR, + PSOP_EQ, + PSOP_NE, + PSOP_GT, + PSOP_GE, + PSOP_LT, + PSOP_LE, + PSOP_AND, + PSOP_OR, + PSOP_XOR, + PSOP_NOT, + PSOP_BITSHIFT, + PSOP_TRUE, + PSOP_FALSE, + PSOP_IF, + PSOP_IFELSE, + PSOP_POP, + PSOP_EXCH, + PSOP_DUP, + PSOP_COPY, + PSOP_INDEX, + PSOP_ROLL, + PSOP_PROC, + PSOP_CONST +}; + +constexpr uint32_t PSENGINE_STACKSIZE = 100; + +class CPDF_PSProc { + public: + CPDF_PSProc(); + ~CPDF_PSProc(); + + FX_BOOL Parse(CPDF_SimpleParser* parser); + FX_BOOL Execute(CPDF_PSEngine* pEngine); + + private: + std::vector> m_Operators; +}; + +class CPDF_PSEngine { + public: + CPDF_PSEngine(); + ~CPDF_PSEngine(); + + FX_BOOL Parse(const FX_CHAR* str, int size); + FX_BOOL Execute(); + FX_BOOL DoOperator(PDF_PSOP op); + void Reset() { m_StackCount = 0; } + void Push(FX_FLOAT value); + void Push(int value) { Push((FX_FLOAT)value); } + FX_FLOAT Pop(); + uint32_t GetStackSize() const { return m_StackCount; } + + private: + FX_FLOAT m_Stack[PSENGINE_STACKSIZE]; + uint32_t m_StackCount; + CPDF_PSProc m_MainProc; +}; + +#endif // CORE_FPDFAPI_FPDF_PAGE_CPDF_PSENGINE_H_ diff --git a/core/fpdfapi/fpdf_page/fpdf_page_func.cpp b/core/fpdfapi/fpdf_page/fpdf_page_func.cpp index ed8e6093d5..6a5bbacda5 100644 --- a/core/fpdfapi/fpdf_page/fpdf_page_func.cpp +++ b/core/fpdfapi/fpdf_page/fpdf_page_func.cpp @@ -13,6 +13,7 @@ #include #include +#include "core/fpdfapi/fpdf_page/cpdf_psengine.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h" @@ -21,58 +22,6 @@ #include "core/fxcrt/include/fx_safe_types.h" #include "third_party/base/numerics/safe_conversions_impl.h" -namespace { - -enum PDF_PSOP { - PSOP_ADD, - PSOP_SUB, - PSOP_MUL, - PSOP_DIV, - PSOP_IDIV, - PSOP_MOD, - PSOP_NEG, - PSOP_ABS, - PSOP_CEILING, - PSOP_FLOOR, - PSOP_ROUND, - PSOP_TRUNCATE, - PSOP_SQRT, - PSOP_SIN, - PSOP_COS, - PSOP_ATAN, - PSOP_EXP, - PSOP_LN, - PSOP_LOG, - PSOP_CVI, - PSOP_CVR, - PSOP_EQ, - PSOP_NE, - PSOP_GT, - PSOP_GE, - PSOP_LT, - PSOP_LE, - PSOP_AND, - PSOP_OR, - PSOP_XOR, - PSOP_NOT, - PSOP_BITSHIFT, - PSOP_TRUE, - PSOP_FALSE, - PSOP_IF, - PSOP_IFELSE, - PSOP_POP, - PSOP_EXCH, - PSOP_DUP, - PSOP_COPY, - PSOP_INDEX, - PSOP_ROLL, - PSOP_PROC, - PSOP_CONST -}; - -class CPDF_PSEngine; -class CPDF_PSProc; - class CPDF_PSOP { public: explicit CPDF_PSOP(PDF_PSOP op) : m_op(op), m_value(0) { @@ -105,39 +54,12 @@ class CPDF_PSOP { std::unique_ptr m_proc; }; -class CPDF_PSProc { - public: - CPDF_PSProc() {} - ~CPDF_PSProc() {} - - FX_BOOL Parse(CPDF_SimpleParser* parser); - FX_BOOL Execute(CPDF_PSEngine* pEngine); - - private: - std::vector> m_Operators; -}; - -const uint32_t PSENGINE_STACKSIZE = 100; - -class CPDF_PSEngine { - public: - CPDF_PSEngine(); - ~CPDF_PSEngine(); - - FX_BOOL Parse(const FX_CHAR* str, int size); - FX_BOOL Execute() { return m_MainProc.Execute(this); } - FX_BOOL DoOperator(PDF_PSOP op); - void Reset() { m_StackCount = 0; } - void Push(FX_FLOAT value); - void Push(int value) { Push((FX_FLOAT)value); } - FX_FLOAT Pop(); - uint32_t GetStackSize() const { return m_StackCount; } +FX_BOOL CPDF_PSEngine::Execute() { + return m_MainProc.Execute(this); +} - private: - FX_FLOAT m_Stack[PSENGINE_STACKSIZE]; - uint32_t m_StackCount; - CPDF_PSProc m_MainProc; -}; +CPDF_PSProc::CPDF_PSProc() {} +CPDF_PSProc::~CPDF_PSProc() {} FX_BOOL CPDF_PSProc::Execute(CPDF_PSEngine* pEngine) { for (size_t i = 0; i < m_Operators.size(); ++i) { @@ -280,12 +202,12 @@ FX_BOOL CPDF_PSEngine::DoOperator(PDF_PSOP op) { case PSOP_IDIV: i2 = (int)Pop(); i1 = (int)Pop(); - Push(i1 / i2); + Push(i2 ? i1 / i2 : 0); break; case PSOP_MOD: i2 = (int)Pop(); i1 = (int)Pop(); - Push(i1 % i2); + Push(i2 ? i1 % i2 : 0); break; case PSOP_NEG: d1 = Pop(); @@ -538,7 +460,6 @@ FX_BOOL CPDF_PSFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const { return TRUE; } -} // namespace CPDF_SampledFunc::CPDF_SampledFunc() : CPDF_Function(Type::kType0Sampled) {} diff --git a/testing/libfuzzer/BUILD.gn b/testing/libfuzzer/BUILD.gn index 1b7a7fb456..718a1db3c0 100644 --- a/testing/libfuzzer/BUILD.gn +++ b/testing/libfuzzer/BUILD.gn @@ -168,3 +168,18 @@ source_set("pdf_jpx_fuzzer") { ":libfuzzer_config", ] } + +source_set("pdf_psengine_fuzzer") { + testonly = true + sources = [ + "pdf_psengine_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/pdf_psengine_fuzzer.cc b/testing/libfuzzer/pdf_psengine_fuzzer.cc new file mode 100644 index 0000000000..89f582ec64 --- /dev/null +++ b/testing/libfuzzer/pdf_psengine_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 "core/fpdfapi/fpdf_page/cpdf_psengine.h" + +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + CPDF_PSEngine engine; + if (engine.Parse(reinterpret_cast(data), size)) + engine.Execute(); + return 0; +} -- cgit v1.2.3