diff options
-rw-r--r-- | BUILD.gn | 1 | ||||
-rw-r--r-- | core/src/fpdfapi/fpdf_page/fpdf_page_func.cpp | 68 | ||||
-rw-r--r-- | core/src/fpdfapi/fpdf_page/fpdf_page_func_embeddertest.cpp | 20 | ||||
-rw-r--r-- | pdfium.gyp | 1 | ||||
-rw-r--r-- | testing/resources/bug_551460.in | 75 | ||||
-rw-r--r-- | testing/resources/bug_551460.pdf | 89 |
6 files changed, 226 insertions, 28 deletions
@@ -739,6 +739,7 @@ test("pdfium_unittests") { test("pdfium_embeddertests") { sources = [ + "core/src/fpdfapi/fpdf_page/fpdf_page_func_embeddertest.cpp", "core/src/fpdfapi/fpdf_parser/fpdf_parser_decode_embeddertest.cpp", "core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_embeddertest.cpp", "core/src/fpdfapi/fpdf_render/fpdf_render_pattern_embeddertest.cpp", diff --git a/core/src/fpdfapi/fpdf_page/fpdf_page_func.cpp b/core/src/fpdfapi/fpdf_page/fpdf_page_func.cpp index 2d35dd85be..e6268037b7 100644 --- a/core/src/fpdfapi/fpdf_page/fpdf_page_func.cpp +++ b/core/src/fpdfapi/fpdf_page/fpdf_page_func.cpp @@ -5,7 +5,9 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include <limits.h> +#include <vector> +#include "../../../../third_party/base/nonstd_unique_ptr.h" #include "../../../../third_party/base/numerics/safe_conversions_impl.h" #include "../../../include/fpdfapi/fpdf_module.h" #include "../../../include/fpdfapi/fpdf_page.h" @@ -724,78 +726,88 @@ class CPDF_StitchFunc : public CPDF_Function { FX_BOOL v_Init(CPDF_Object* pObj) override; FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override; - int m_nSubs; - CPDF_Function** m_pSubFunctions; + std::vector<CPDF_Function*> m_pSubFunctions; FX_FLOAT* m_pBounds; FX_FLOAT* m_pEncode; + + static const int kRequiredNumInputs = 1; }; CPDF_StitchFunc::CPDF_StitchFunc() { - m_nSubs = 0; - m_pSubFunctions = NULL; m_pBounds = NULL; m_pEncode = NULL; } CPDF_StitchFunc::~CPDF_StitchFunc() { - for (int i = 0; i < m_nSubs; i++) - delete m_pSubFunctions[i]; - FX_Free(m_pSubFunctions); + for (auto& sub : m_pSubFunctions) { + delete sub; + } FX_Free(m_pBounds); FX_Free(m_pEncode); } FX_BOOL CPDF_StitchFunc::v_Init(CPDF_Object* pObj) { CPDF_Dictionary* pDict = pObj->GetDict(); - if (pDict == NULL) { + if (!pDict) { + return FALSE; + } + if (m_nInputs != kRequiredNumInputs) { return FALSE; } CPDF_Array* pArray = pDict->GetArray(FX_BSTRC("Functions")); - if (pArray == NULL) { + if (!pArray) { return FALSE; } - m_nSubs = pArray->GetCount(); - if (m_nSubs == 0) { + FX_DWORD nSubs = pArray->GetCount(); + if (nSubs == 0) { return FALSE; } - m_pSubFunctions = FX_Alloc(CPDF_Function*, m_nSubs); m_nOutputs = 0; - int i; - for (i = 0; i < m_nSubs; i++) { + for (FX_DWORD i = 0; i < nSubs; i++) { CPDF_Object* pSub = pArray->GetElementValue(i); if (pSub == pObj) { return FALSE; } - m_pSubFunctions[i] = CPDF_Function::Load(pSub); - if (m_pSubFunctions[i] == NULL) { + nonstd::unique_ptr<CPDF_Function> pFunc(CPDF_Function::Load(pSub)); + if (!pFunc) { return FALSE; } - if (m_pSubFunctions[i]->CountOutputs() > m_nOutputs) { - m_nOutputs = m_pSubFunctions[i]->CountOutputs(); + // Check that the input dimensionality is 1, and that all output + // dimensionalities are the same. + if (pFunc->CountInputs() != kRequiredNumInputs) { + return FALSE; + } + if (pFunc->CountOutputs() != m_nOutputs) { + if (m_nOutputs) + return FALSE; + + m_nOutputs = pFunc->CountOutputs(); } + + m_pSubFunctions.push_back(pFunc.release()); } - m_pBounds = FX_Alloc(FX_FLOAT, m_nSubs + 1); + m_pBounds = FX_Alloc(FX_FLOAT, nSubs + 1); m_pBounds[0] = m_pDomains[0]; pArray = pDict->GetArray(FX_BSTRC("Bounds")); - if (pArray == NULL) { + if (!pArray) { return FALSE; } - for (i = 0; i < m_nSubs - 1; i++) { + for (FX_DWORD i = 0; i < nSubs - 1; i++) { m_pBounds[i + 1] = pArray->GetFloat(i); } - m_pBounds[m_nSubs] = m_pDomains[1]; - m_pEncode = FX_Alloc2D(FX_FLOAT, m_nSubs, 2); + m_pBounds[nSubs] = m_pDomains[1]; + m_pEncode = FX_Alloc2D(FX_FLOAT, nSubs, 2); pArray = pDict->GetArray(FX_BSTRC("Encode")); - if (pArray == NULL) { + if (!pArray) { return FALSE; } - for (i = 0; i < m_nSubs * 2; i++) { + for (FX_DWORD i = 0; i < nSubs * 2; i++) { m_pEncode[i] = pArray->GetFloat(i); } return TRUE; } FX_BOOL CPDF_StitchFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* outputs) const { FX_FLOAT input = inputs[0]; - int i; - for (i = 0; i < m_nSubs - 1; i++) + size_t i; + for (i = 0; i < m_pSubFunctions.size() - 1; i++) if (input < m_pBounds[i + 1]) { break; } @@ -805,7 +817,7 @@ FX_BOOL CPDF_StitchFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* outputs) const { input = PDF_Interpolate(input, m_pBounds[i], m_pBounds[i + 1], m_pEncode[i * 2], m_pEncode[i * 2 + 1]); int nresults; - m_pSubFunctions[i]->Call(&input, m_nInputs, outputs, nresults); + m_pSubFunctions[i]->Call(&input, kRequiredNumInputs, outputs, nresults); return TRUE; } CPDF_Function* CPDF_Function::Load(CPDF_Object* pFuncObj) { diff --git a/core/src/fpdfapi/fpdf_page/fpdf_page_func_embeddertest.cpp b/core/src/fpdfapi/fpdf_page/fpdf_page_func_embeddertest.cpp new file mode 100644 index 0000000000..af04b4aebb --- /dev/null +++ b/core/src/fpdfapi/fpdf_page/fpdf_page_func_embeddertest.cpp @@ -0,0 +1,20 @@ +// Copyright 2015 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/embedder_test.h" +#include "testing/gtest/include/gtest/gtest.h" + +class FPDFPageFuncEmbeddertest : public EmbedderTest {}; + +TEST_F(FPDFPageFuncEmbeddertest, Bug_551460) { + // Should not crash under ASan. + // Tests that the number of inputs is not simply calculated from the domain + // and trusted. The number of inputs has to be 1. + EXPECT_TRUE(OpenDocument("testing/resources/bug_551460.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_NE(nullptr, page); + FPDF_BITMAP bitmap = RenderPage(page); + FPDFBitmap_Destroy(bitmap); + UnloadPage(page); +} diff --git a/pdfium.gyp b/pdfium.gyp index 1afadaa672..17d4336495 100644 --- a/pdfium.gyp +++ b/pdfium.gyp @@ -743,6 +743,7 @@ '<(DEPTH)', ], 'sources': [ + 'core/src/fpdfapi/fpdf_page/fpdf_page_func_embeddertest.cpp', 'core/src/fpdfapi/fpdf_parser/fpdf_parser_decode_embeddertest.cpp', 'core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_embeddertest.cpp', 'core/src/fpdfapi/fpdf_render/fpdf_render_pattern_embeddertest.cpp', diff --git a/testing/resources/bug_551460.in b/testing/resources/bug_551460.in new file mode 100644 index 0000000000..5ed2f3f117 --- /dev/null +++ b/testing/resources/bug_551460.in @@ -0,0 +1,75 @@ +{{header}} + +{{object 1 0}} +<< + /Pages 2 0 R +>> +endobj + +{{object 2 0}} +<< + /Kids [ 3 0 R ] +>> +endobj + +{{object 3 0}} +<< + /Contents 6 0 R + /Resources 5 0 R +>> +endobj + +{{object 6 0}} +<<>> +stream +0.0 G +0.0 1.0 0.0 rg +25 175 175 -150 re +/Sh sh +endstream +endobj + +{{object 5 0}} +<< + /Shading << + /Sh 7 0 R + >> +>> +endobj + +{{object 7 0}} +<< + /ShadingType 1 + /ColorSpace /DeviceCMYK + /Coords [0.0 0.0 1.0 1.0] + /Function 9 0 R + /Extend [true true] +>> + +{{object 9 0}} +<< + /FunctionType 3 + /Domain [0.0 1.0 0.0 1.0] + /Functions [10 0 R] + /Bounds [2.0] + /Encode [0.0 1.0] +>> +endobj + +{{object 10 0}} +<< + /FunctionType 2 + /Domain [0.0 1.0 0.0 1.0] + /C0 [0.0 0.0] + /C1 [1.0 1.0] + /N 1 +>> +endobj + +{{xref}} +trailer << + /Root 1 0 R + /Size 11 +>> +{{startxref}} +%%EOF diff --git a/testing/resources/bug_551460.pdf b/testing/resources/bug_551460.pdf new file mode 100644 index 0000000000..926e3fad2d --- /dev/null +++ b/testing/resources/bug_551460.pdf @@ -0,0 +1,89 @@ +%PDF-1.7 +% ò¤ô + +1 0 obj +<< + /Pages 2 0 R +>> +endobj + +2 0 obj +<< + /Kids [ 3 0 R ] +>> +endobj + +3 0 obj +<< + /Contents 6 0 R + /Resources 5 0 R +>> +endobj + +6 0 obj +<<>> +stream +0.0 G +0.0 1.0 0.0 rg +25 175 175 -150 re +/Sh sh +endstream +endobj + +5 0 obj +<< + /Shading << + /Sh 7 0 R + >> +>> +endobj + +7 0 obj +<< + /ShadingType 1 + /ColorSpace /DeviceCMYK + /Coords [0.0 0.0 1.0 1.0] + /Function 9 0 R + /Extend [true true] +>> + +9 0 obj +<< + /FunctionType 3 + /Domain [0.0 1.0 0.0 1.0] + /Functions [10 0 R] + /Bounds [2.0] + /Encode [0.0 1.0] +>> +endobj + +10 0 obj +<< + /FunctionType 2 + /Domain [0.0 1.0 0.0 1.0] + /C0 [0.0 0.0] + /C1 [1.0 1.0] + /N 1 +>> +endobj + +xref +0 11 +0000000000 65535 f +0000000016 00000 n +0000000053 00000 n +0000000093 00000 n +0000000000 65535 f +0000000237 00000 n +0000000152 00000 n +0000000292 00000 n +0000000000 65535 f +0000000418 00000 n +0000000544 00000 n +trailer << + /Root 1 0 R + /Size 11 +>> +startxref +652 +%%EOF |