summaryrefslogtreecommitdiff
path: root/core/fpdfapi/page/cpdf_stitchfunc.cpp
diff options
context:
space:
mode:
authorLei Zhang <thestig@chromium.org>2018-04-19 16:54:12 +0000
committerChromium commit bot <commit-bot@chromium.org>2018-04-19 16:54:12 +0000
commit09f2855f196d4269477641413082f7d83eeb7d75 (patch)
treec8c69c08f0e01d3094edbf98b5a68189a3a09150 /core/fpdfapi/page/cpdf_stitchfunc.cpp
parent93358c23262e27ead528ac60607329ba0ea0a49a (diff)
downloadpdfium-09f2855f196d4269477641413082f7d83eeb7d75.tar.xz
Do more validation in CPDF_StitchFunc::v_Init().
Change-Id: I8eeaf62947960d8774cb129be145fae157feb70e Reviewed-on: https://pdfium-review.googlesource.com/30970 Commit-Queue: Lei Zhang <thestig@chromium.org> Reviewed-by: Henrique Nakashima <hnakashima@chromium.org>
Diffstat (limited to 'core/fpdfapi/page/cpdf_stitchfunc.cpp')
-rw-r--r--core/fpdfapi/page/cpdf_stitchfunc.cpp103
1 files changed, 68 insertions, 35 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<CPDF_Object*>* 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<CPDF_Function> 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<uint32_t> 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<CPDF_Function> 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;
}