Fix nits in CPDF_Function and derived classes.

- Switch away from FX_Alloc2D() when it is safe to do so.
- Use FX_SAFE_SIZE_T to avoid a potential underflow with FX_Realloc().
- Mark the v_Call() input as const.
- Check Call() and v_Call() return results.

Change-Id: I6ec3122b23e0f137f88aa8d85a9675154a1b1706
Reviewed-on: https://pdfium-review.googlesource.com/30802
Reviewed-by: Henrique Nakashima <hnakashima@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_colorspace.cpp b/core/fpdfapi/page/cpdf_colorspace.cpp
index 7fdee86..8ba2d8b 100644
--- a/core/fpdfapi/page/cpdf_colorspace.cpp
+++ b/core/fpdfapi/page/cpdf_colorspace.cpp
@@ -1214,8 +1214,7 @@
 
   CFX_FixedBufGrow<float, 16> results(m_pFunc->CountOutputs());
   int nresults = 0;
-  m_pFunc->Call(pBuf, 1, results, &nresults);
-  if (nresults == 0)
+  if (!m_pFunc->Call(pBuf, 1, results, &nresults) || nresults == 0)
     return false;
 
   if (m_pAltCS)
@@ -1281,9 +1280,10 @@
 
   CFX_FixedBufGrow<float, 16> results(m_pFunc->CountOutputs());
   int nresults = 0;
-  m_pFunc->Call(pBuf, CountComponents(), results, &nresults);
-  if (nresults == 0)
+  if (!m_pFunc->Call(pBuf, CountComponents(), results, &nresults) ||
+      nresults == 0) {
     return false;
+  }
 
   return m_pAltCS->GetRGB(results, R, G, B);
 }
diff --git a/core/fpdfapi/page/cpdf_expintfunc.cpp b/core/fpdfapi/page/cpdf_expintfunc.cpp
index f26df1b..020fe1f 100644
--- a/core/fpdfapi/page/cpdf_expintfunc.cpp
+++ b/core/fpdfapi/page/cpdf_expintfunc.cpp
@@ -50,7 +50,7 @@
   return true;
 }
 
-bool CPDF_ExpIntFunc::v_Call(float* inputs, float* results) const {
+bool CPDF_ExpIntFunc::v_Call(const float* inputs, float* results) const {
   for (uint32_t i = 0; i < m_nInputs; i++)
     for (uint32_t j = 0; j < m_nOrigOutputs; j++) {
       results[i * m_nOrigOutputs + j] =
diff --git a/core/fpdfapi/page/cpdf_expintfunc.h b/core/fpdfapi/page/cpdf_expintfunc.h
index f46d6c2..7950c3d 100644
--- a/core/fpdfapi/page/cpdf_expintfunc.h
+++ b/core/fpdfapi/page/cpdf_expintfunc.h
@@ -18,7 +18,7 @@
 
   // CPDF_Function
   bool v_Init(CPDF_Object* pObj, std::set<CPDF_Object*>* pVisited) override;
-  bool v_Call(float* inputs, float* results) const override;
+  bool v_Call(const float* inputs, float* results) const override;
 
   uint32_t m_nOrigOutputs;
   float m_Exponent;
diff --git a/core/fpdfapi/page/cpdf_function.cpp b/core/fpdfapi/page/cpdf_function.cpp
index d4fad9c..ce119ca 100644
--- a/core/fpdfapi/page/cpdf_function.cpp
+++ b/core/fpdfapi/page/cpdf_function.cpp
@@ -27,9 +27,8 @@
 std::unique_ptr<CPDF_Function> CPDF_Function::Load(
     CPDF_Object* pFuncObj,
     std::set<CPDF_Object*>* pVisited) {
-  std::unique_ptr<CPDF_Function> pFunc;
   if (!pFuncObj)
-    return pFunc;
+    return nullptr;
 
   if (pdfium::ContainsKey(*pVisited, pFuncObj))
     return nullptr;
@@ -41,6 +40,7 @@
   else if (CPDF_Dictionary* pDict = pFuncObj->AsDictionary())
     iType = pDict->GetIntegerFor("FunctionType");
 
+  std::unique_ptr<CPDF_Function> pFunc;
   Type type = IntegerToFunctionType(iType);
   if (type == Type::kType0Sampled)
     pFunc = pdfium::MakeUnique<CPDF_SampledFunc>();
@@ -90,16 +90,20 @@
   if (m_nInputs == 0)
     return false;
 
-  m_pDomains = FX_Alloc2D(float, m_nInputs, 2);
-  for (uint32_t i = 0; i < m_nInputs * 2; i++) {
-    m_pDomains[i] = pDomains->GetFloatAt(i);
+  {
+    size_t nInputs = m_nInputs * 2;
+    m_pDomains = FX_Alloc(float, nInputs);
+    for (size_t i = 0; i < nInputs; ++i)
+      m_pDomains[i] = pDomains->GetFloatAt(i);
   }
+
   CPDF_Array* pRanges = pDict->GetArrayFor("Range");
   m_nOutputs = 0;
   if (pRanges) {
     m_nOutputs = pRanges->GetCount() / 2;
-    m_pRanges = FX_Alloc2D(float, m_nOutputs, 2);
-    for (uint32_t i = 0; i < m_nOutputs * 2; i++)
+    size_t nOutputs = m_nOutputs * 2;
+    m_pRanges = FX_Alloc(float, nOutputs);
+    for (size_t i = 0; i < nOutputs; ++i)
       m_pRanges[i] = pRanges->GetFloatAt(i);
   }
   uint32_t old_outputs = m_nOutputs;
@@ -107,7 +111,9 @@
     return false;
 
   if (m_pRanges && m_nOutputs > old_outputs) {
-    m_pRanges = FX_Realloc(float, m_pRanges, m_nOutputs * 2);
+    FX_SAFE_SIZE_T nOutputs = m_nOutputs;
+    nOutputs *= 2;
+    m_pRanges = FX_Realloc(float, m_pRanges, nOutputs.ValueOrDie());
     memset(m_pRanges + (old_outputs * 2), 0,
            sizeof(float) * (m_nOutputs - old_outputs) * 2);
   }
@@ -127,7 +133,9 @@
     clamped_inputs[i] =
         pdfium::clamp(inputs[i], m_pDomains[i * 2], m_pDomains[i * 2 + 1]);
   }
-  v_Call(clamped_inputs.data(), results);
+  if (!v_Call(clamped_inputs.data(), results))
+    return false;
+
   if (!m_pRanges)
     return true;
 
diff --git a/core/fpdfapi/page/cpdf_function.h b/core/fpdfapi/page/cpdf_function.h
index 615c6a6..82a3a54 100644
--- a/core/fpdfapi/page/cpdf_function.h
+++ b/core/fpdfapi/page/cpdf_function.h
@@ -55,12 +55,14 @@
                                              std::set<CPDF_Object*>* pVisited);
   bool Init(CPDF_Object* pObj, std::set<CPDF_Object*>* pVisited);
   virtual bool v_Init(CPDF_Object* pObj, std::set<CPDF_Object*>* pVisited) = 0;
-  virtual bool v_Call(float* inputs, float* results) const = 0;
+  virtual bool v_Call(const float* inputs, float* results) const = 0;
 
   uint32_t m_nInputs;
   uint32_t m_nOutputs;
   float* m_pDomains;
   float* m_pRanges;
+
+ private:
   const Type m_Type;
 };
 
diff --git a/core/fpdfapi/page/cpdf_psfunc.cpp b/core/fpdfapi/page/cpdf_psfunc.cpp
index 6df7dff..2230d4e 100644
--- a/core/fpdfapi/page/cpdf_psfunc.cpp
+++ b/core/fpdfapi/page/cpdf_psfunc.cpp
@@ -19,7 +19,7 @@
   return m_PS.Parse(pAcc->GetSpan());
 }
 
-bool CPDF_PSFunc::v_Call(float* inputs, float* results) const {
+bool CPDF_PSFunc::v_Call(const float* inputs, float* results) const {
   CPDF_PSEngine& PS = const_cast<CPDF_PSEngine&>(m_PS);
   PS.Reset();
   for (uint32_t i = 0; i < m_nInputs; i++)
diff --git a/core/fpdfapi/page/cpdf_psfunc.h b/core/fpdfapi/page/cpdf_psfunc.h
index 7212fea..b4bc5bd 100644
--- a/core/fpdfapi/page/cpdf_psfunc.h
+++ b/core/fpdfapi/page/cpdf_psfunc.h
@@ -21,7 +21,7 @@
 
   // CPDF_Function
   bool v_Init(CPDF_Object* pObj, std::set<CPDF_Object*>* pVisited) override;
-  bool v_Call(float* inputs, float* results) const override;
+  bool v_Call(const float* inputs, float* results) const override;
 
  private:
   CPDF_PSEngine m_PS;
diff --git a/core/fpdfapi/page/cpdf_sampledfunc.cpp b/core/fpdfapi/page/cpdf_sampledfunc.cpp
index 78c4f2c..205ce91 100644
--- a/core/fpdfapi/page/cpdf_sampledfunc.cpp
+++ b/core/fpdfapi/page/cpdf_sampledfunc.cpp
@@ -91,7 +91,7 @@
   return true;
 }
 
-bool CPDF_SampledFunc::v_Call(float* inputs, float* results) const {
+bool CPDF_SampledFunc::v_Call(const float* inputs, float* results) const {
   int pos = 0;
   CFX_FixedBufGrow<float, 16> encoded_input_buf(m_nInputs);
   float* encoded_input = encoded_input_buf;
diff --git a/core/fpdfapi/page/cpdf_sampledfunc.h b/core/fpdfapi/page/cpdf_sampledfunc.h
index b06b14b..cbf2dd3 100644
--- a/core/fpdfapi/page/cpdf_sampledfunc.h
+++ b/core/fpdfapi/page/cpdf_sampledfunc.h
@@ -32,7 +32,7 @@
 
   // CPDF_Function
   bool v_Init(CPDF_Object* pObj, std::set<CPDF_Object*>* pVisited) override;
-  bool v_Call(float* inputs, float* results) const override;
+  bool v_Call(const float* inputs, float* results) const override;
 
   const std::vector<SampleEncodeInfo>& GetEncodeInfo() const {
     return m_EncodeInfo;
diff --git a/core/fpdfapi/page/cpdf_stitchfunc.cpp b/core/fpdfapi/page/cpdf_stitchfunc.cpp
index fd83fd6..1d0250b 100644
--- a/core/fpdfapi/page/cpdf_stitchfunc.cpp
+++ b/core/fpdfapi/page/cpdf_stitchfunc.cpp
@@ -77,7 +77,7 @@
   return true;
 }
 
-bool CPDF_StitchFunc::v_Call(float* inputs, float* outputs) const {
+bool CPDF_StitchFunc::v_Call(const float* inputs, float* results) const {
   float input = inputs[0];
   size_t i;
   for (i = 0; i < m_pSubFunctions.size() - 1; i++) {
@@ -87,6 +87,6 @@
   input = 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, kRequiredNumInputs, outputs, &nresults);
-  return true;
+  return m_pSubFunctions[i]->Call(&input, kRequiredNumInputs, results,
+                                  &nresults);
 }
diff --git a/core/fpdfapi/page/cpdf_stitchfunc.h b/core/fpdfapi/page/cpdf_stitchfunc.h
index 11396f1..1d11cb0 100644
--- a/core/fpdfapi/page/cpdf_stitchfunc.h
+++ b/core/fpdfapi/page/cpdf_stitchfunc.h
@@ -20,7 +20,7 @@
 
   // CPDF_Function
   bool v_Init(CPDF_Object* pObj, std::set<CPDF_Object*>* pVisited) override;
-  bool v_Call(float* inputs, float* results) const override;
+  bool v_Call(const float* inputs, float* results) const override;
 
   const std::vector<std::unique_ptr<CPDF_Function>>& GetSubFunctions() const {
     return m_pSubFunctions;