From 09f2855f196d4269477641413082f7d83eeb7d75 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Thu, 19 Apr 2018 16:54:12 +0000 Subject: Do more validation in CPDF_StitchFunc::v_Init(). Change-Id: I8eeaf62947960d8774cb129be145fae157feb70e Reviewed-on: https://pdfium-review.googlesource.com/30970 Commit-Queue: Lei Zhang Reviewed-by: Henrique Nakashima --- core/fpdfapi/page/cpdf_stitchfunc.cpp | 103 ++++++++++++++++++++++------------ core/fpdfapi/page/cpdf_stitchfunc.h | 6 +- 2 files changed, 70 insertions(+), 39 deletions(-) diff --git a/core/fpdfapi/page/cpdf_stitchfunc.cpp b/core/fpdfapi/page/cpdf_stitchfunc.cpp index 1d0250bfad..1e5329b337 100644 --- a/core/fpdfapi/page/cpdf_stitchfunc.cpp +++ b/core/fpdfapi/page/cpdf_stitchfunc.cpp @@ -12,10 +12,13 @@ #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fxcrt/fx_memory.h" -CPDF_StitchFunc::CPDF_StitchFunc() - : CPDF_Function(Type::kType3Stitching), - m_pBounds(nullptr), - m_pEncode(nullptr) {} +namespace { + +constexpr uint32_t kRequiredNumInputs = 1; + +} // namespace + +CPDF_StitchFunc::CPDF_StitchFunc() : CPDF_Function(Type::kType3Stitching) {} CPDF_StitchFunc::~CPDF_StitchFunc() { FX_Free(m_pBounds); @@ -24,56 +27,86 @@ CPDF_StitchFunc::~CPDF_StitchFunc() { bool CPDF_StitchFunc::v_Init(CPDF_Object* pObj, std::set* pVisited) { + if (m_nInputs != kRequiredNumInputs) + return false; + CPDF_Dictionary* pDict = pObj->GetDict(); - if (!pDict) { + if (!pDict) return false; - } - if (m_nInputs != kRequiredNumInputs) { + + const CPDF_Array* pFunctionsArray = pDict->GetArrayFor("Functions"); + if (!pFunctionsArray) return false; - } - CPDF_Array* pArray = pDict->GetArrayFor("Functions"); - if (!pArray) { + + const CPDF_Array* pBoundsArray = pDict->GetArrayFor("Bounds"); + if (!pBoundsArray) return false; - } - uint32_t nSubs = pArray->GetCount(); + + const CPDF_Array* pEncodeArray = pDict->GetArrayFor("Encode"); + if (!pEncodeArray) + return false; + + const uint32_t nSubs = pFunctionsArray->GetCount(); if (nSubs == 0) return false; - m_nOutputs = 0; - for (uint32_t i = 0; i < nSubs; i++) { - CPDF_Object* pSub = pArray->GetDirectObjectAt(i); - if (pSub == pObj) + + // Check array sizes. The checks are slightly relaxed to allow the "Bounds" + // and "Encode" arrays to have more than the required number of elements. + { + if (pBoundsArray->GetCount() < nSubs - 1) return false; - std::unique_ptr pFunc(CPDF_Function::Load(pSub, pVisited)); - if (!pFunc) + + FX_SAFE_UINT32 nExpectedEncodeSize = nSubs; + nExpectedEncodeSize *= 2; + if (!nExpectedEncodeSize.IsValid()) return false; - // Check that the input dimensionality is 1, and that all output - // dimensionalities are the same. - if (pFunc->CountInputs() != kRequiredNumInputs) + + if (pEncodeArray->GetCount() < nExpectedEncodeSize.ValueOrDie()) return false; - if (pFunc->CountOutputs() != m_nOutputs) { - if (m_nOutputs) + } + + // Check sub-functions. + { + Optional nOutputs; + for (uint32_t i = 0; i < nSubs; ++i) { + CPDF_Object* pSub = pFunctionsArray->GetDirectObjectAt(i); + if (pSub == pObj) return false; - m_nOutputs = pFunc->CountOutputs(); - } + std::unique_ptr pFunc(CPDF_Function::Load(pSub, pVisited)); + if (!pFunc) + return false; + + // Check that the input dimensionality is 1, and that all output + // dimensionalities are the same. + if (pFunc->CountInputs() != kRequiredNumInputs) + return false; + + uint32_t nFuncOutputs = pFunc->CountOutputs(); + if (nFuncOutputs == 0) + return false; - m_pSubFunctions.push_back(std::move(pFunc)); + if (nOutputs) { + if (nFuncOutputs != *nOutputs) + return false; + } else { + nOutputs = nFuncOutputs; + } + + m_pSubFunctions.push_back(std::move(pFunc)); + } + m_nOutputs = *nOutputs; } + m_pBounds = FX_Alloc(float, nSubs + 1); m_pBounds[0] = m_pDomains[0]; - pArray = pDict->GetArrayFor("Bounds"); - if (!pArray) - return false; for (uint32_t i = 0; i < nSubs - 1; i++) - m_pBounds[i + 1] = pArray->GetFloatAt(i); + m_pBounds[i + 1] = pBoundsArray->GetFloatAt(i); m_pBounds[nSubs] = m_pDomains[1]; - m_pEncode = FX_Alloc2D(float, nSubs, 2); - pArray = pDict->GetArrayFor("Encode"); - if (!pArray) - return false; + m_pEncode = FX_Alloc2D(float, nSubs, 2); for (uint32_t i = 0; i < nSubs * 2; i++) - m_pEncode[i] = pArray->GetFloatAt(i); + m_pEncode[i] = pEncodeArray->GetFloatAt(i); return true; } diff --git a/core/fpdfapi/page/cpdf_stitchfunc.h b/core/fpdfapi/page/cpdf_stitchfunc.h index 1d11cb072b..360b789072 100644 --- a/core/fpdfapi/page/cpdf_stitchfunc.h +++ b/core/fpdfapi/page/cpdf_stitchfunc.h @@ -29,10 +29,8 @@ class CPDF_StitchFunc : public CPDF_Function { private: std::vector> m_pSubFunctions; - float* m_pBounds; - float* m_pEncode; - - static const uint32_t kRequiredNumInputs = 1; + float* m_pBounds = nullptr; + float* m_pEncode = nullptr; }; #endif // CORE_FPDFAPI_PAGE_CPDF_STITCHFUNC_H_ -- cgit v1.2.3