Revert "Revert "Redo range check in CPDF_SampledFunc::v_Call().""
[pdfium.git] / core / src / fpdfapi / fpdf_page / fpdf_page_func.cpp
index f1a8433..c961f8b 100644 (file)
@@ -1,7 +1,7 @@
 // Copyright 2014 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
 
 #include <limits.h>
@@ -21,7 +21,7 @@ typedef enum {PSOP_ADD, PSOP_SUB, PSOP_MUL, PSOP_DIV, PSOP_IDIV, PSOP_MOD,
               PSOP_IF, PSOP_IFELSE, PSOP_POP, PSOP_EXCH, PSOP_DUP, PSOP_COPY,
               PSOP_INDEX, PSOP_ROLL, PSOP_PROC, PSOP_CONST
              } PDF_PSOP;
-class CPDF_PSProc 
+class CPDF_PSProc
 {
 public:
     ~CPDF_PSProc();
@@ -30,7 +30,7 @@ public:
     CFX_PtrArray               m_Operators;
 };
 #define PSENGINE_STACKSIZE 100
-class CPDF_PSEngine 
+class CPDF_PSEngine
 {
 public:
     CPDF_PSEngine();
@@ -449,7 +449,8 @@ public:
     virtual FX_BOOL            v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const;
     SampleEncodeInfo*  m_pEncodeInfo;
     SampleDecodeInfo*  m_pDecodeInfo;
-    FX_DWORD   m_nBitsPerSample, m_SampleMax;
+    FX_DWORD   m_nBitsPerSample;
+    FX_DWORD   m_SampleMax;
     CPDF_StreamAcc*    m_pSampleStream;
 };
 CPDF_SampledFunc::CPDF_SampledFunc()
@@ -460,9 +461,7 @@ CPDF_SampledFunc::CPDF_SampledFunc()
 }
 CPDF_SampledFunc::~CPDF_SampledFunc()
 {
-    if (m_pSampleStream) {
-        delete m_pSampleStream;
-    }
+    delete m_pSampleStream;
     if (m_pEncodeInfo) {
         FX_Free(m_pEncodeInfo);
     }
@@ -481,21 +480,20 @@ FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj)
     CPDF_Array* pEncode = pDict->GetArray(FX_BSTRC("Encode"));
     CPDF_Array* pDecode = pDict->GetArray(FX_BSTRC("Decode"));
     m_nBitsPerSample = pDict->GetInteger(FX_BSTRC("BitsPerSample"));
+    if (m_nBitsPerSample > 32) {
+        return FALSE;
+    }
     m_SampleMax = 0xffffffff >> (32 - m_nBitsPerSample);
     m_pSampleStream = new CPDF_StreamAcc;
     m_pSampleStream->LoadAllData(pStream, FALSE);
     m_pEncodeInfo = FX_Alloc(SampleEncodeInfo, m_nInputs);
-    int i;
-    FX_DWORD nTotalSamples = 1;
-    for (i = 0; i < m_nInputs; i ++) {
+    FX_SAFE_DWORD nTotalSampleBits = 1;
+    for (int i = 0; i < m_nInputs; i ++) {
         m_pEncodeInfo[i].sizes = pSize ? pSize->GetInteger(i) : 0;
         if (!pSize && i == 0) {
             m_pEncodeInfo[i].sizes = pDict->GetInteger(FX_BSTRC("Size"));
         }
-        if (nTotalSamples > 0 && (uint32_t)(m_pEncodeInfo[i].sizes) > UINT_MAX / nTotalSamples) {
-            return FALSE;
-        }
-        nTotalSamples *= m_pEncodeInfo[i].sizes;
+        nTotalSampleBits *= m_pEncodeInfo[i].sizes;
         if (pEncode) {
             m_pEncodeInfo[i].encode_min = pEncode->GetFloat(i * 2);
             m_pEncodeInfo[i].encode_max = pEncode->GetFloat(i * 2 + 1);
@@ -508,19 +506,18 @@ FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj)
             }
         }
     }
-    if (nTotalSamples > 0 && m_nBitsPerSample > UINT_MAX / nTotalSamples) {
-        return FALSE;
-    }
-    nTotalSamples *= m_nBitsPerSample;
-    if (nTotalSamples > 0 && ((uint32_t)m_nOutputs) > UINT_MAX / nTotalSamples) {
-        return FALSE;
-    }
-    nTotalSamples *= m_nOutputs;
-    if (nTotalSamples == 0 || m_pSampleStream->GetSize() * 8 < nTotalSamples) {
+    nTotalSampleBits *= m_nBitsPerSample;
+    nTotalSampleBits *= m_nOutputs;
+    FX_SAFE_DWORD nTotalSampleBytes = nTotalSampleBits;
+    nTotalSampleBytes += 7;
+    nTotalSampleBytes /= 8;
+    if (!nTotalSampleBytes.IsValid() ||
+        nTotalSampleBytes.ValueOrDie() == 0 ||
+        nTotalSampleBytes.ValueOrDie() > m_pSampleStream->GetSize()) {
         return FALSE;
     }
     m_pDecodeInfo = FX_Alloc(SampleDecodeInfo, m_nOutputs);
-    for (i = 0; i < m_nOutputs; i ++) {
+    for (int i = 0; i < m_nOutputs; i ++) {
         if (pDecode) {
             m_pDecodeInfo[i].decode_min = pDecode->GetFloat(2 * i);
             m_pDecodeInfo[i].decode_max = pDecode->GetFloat(2 * i + 1);
@@ -555,20 +552,23 @@ FX_BOOL CPDF_SampledFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const
         }
         pos += index[i] * blocksize[i];
     }
+    FX_SAFE_INT32 bits_to_output = m_nOutputs;
+    bits_to_output *= m_nBitsPerSample;
+    if (!bits_to_output.IsValid()) {
+        return FALSE;
+    }
     FX_SAFE_INT32 bitpos = pos;
-    bitpos *= m_nBitsPerSample;
-    bitpos *= m_nOutputs;
+    bitpos *= bits_to_output.ValueOrDie();
     if (!bitpos.IsValid()) {
         return FALSE;
     }
-    const uint8_t* pSampleData = m_pSampleStream->GetData();
-    if (pSampleData == NULL) {
+    FX_SAFE_INT32 range_check = bitpos;
+    range_check += bits_to_output.ValueOrDie();
+    if (!range_check.IsValid()) {
         return FALSE;
     }
-    FX_SAFE_INT32 bitpos1 = m_nOutputs - 1 > 0 ? m_nOutputs - 1 : 0; 
-    bitpos1 *= m_nBitsPerSample;
-    bitpos1 += bitpos.ValueOrDie();
-    if (!bitpos1.IsValid()) {
+    const uint8_t* pSampleData = m_pSampleStream->GetData();
+    if (!pSampleData) {
         return FALSE;
     }
     for (int j = 0; j < m_nOutputs; j ++) {
@@ -584,7 +584,7 @@ FX_BOOL CPDF_SampledFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const
                 bitpos2 += pos;
                 bitpos2 *= m_nOutputs;
                 bitpos2 += j;
-                bitpos2 *= m_nBitsPerSample; 
+                bitpos2 *= m_nBitsPerSample;
                 if (!bitpos2.IsValid()) {
                     return FALSE;
                 }
@@ -713,9 +713,7 @@ CPDF_StitchFunc::CPDF_StitchFunc()
 CPDF_StitchFunc::~CPDF_StitchFunc()
 {
     for (int i = 0; i < m_nSubs; i ++)
-        if (m_pSubFunctions[i]) {
-            delete m_pSubFunctions[i];
-        }
+        delete m_pSubFunctions[i];
     if (m_pSubFunctions) {
         FX_Free(m_pSubFunctions);
     }
@@ -869,14 +867,16 @@ FX_BOOL CPDF_Function::Init(CPDF_Object* pObj)
         }
     }
     FX_DWORD old_outputs = m_nOutputs;
-    FX_BOOL ret = v_Init(pObj);
+    if (!v_Init(pObj)) {
+        return FALSE;
+    }
     if (m_pRanges && m_nOutputs > (int)old_outputs) {
         m_pRanges = FX_Realloc(FX_FLOAT, m_pRanges, m_nOutputs * 2);
         if (m_pRanges) {
             FXSYS_memset(m_pRanges + (old_outputs * 2), 0, sizeof(FX_FLOAT) * (m_nOutputs - old_outputs) * 2);
         }
     }
-    return ret;
+    return TRUE;
 }
 FX_BOOL CPDF_Function::Call(FX_FLOAT* inputs, int ninputs, FX_FLOAT* results, int& nresults) const
 {