Redo range check in CPDF_SampledFunc::v_Call().
authorTom Sepez <tsepez@chromium.org>
Tue, 30 Jun 2015 19:18:55 +0000 (12:18 -0700)
committerTom Sepez <tsepez@chromium.org>
Tue, 30 Jun 2015 19:18:55 +0000 (12:18 -0700)
The current |bitpos1| calculation protects the passed argument to
_GetBits32(): |bitpos.ValueOrDie() + j * m_nBitsPerSample|, but doesn't
account for adding in the sample length in that routine.

Also bound bits per sample to something reasonable to avoid undefined
behaviour on the shift to compute the max value.

BUG=471990
R=jun_fang@foxitsoftware.com

Review URL: https://codereview.chromium.org/1219663003.

core/src/fpdfapi/fpdf_page/fpdf_page_func.cpp
fpdfsdk/src/fpdfview_embeddertest.cpp
testing/resources/bug_471990.in [new file with mode: 0644]
testing/resources/bug_471990.pdf [new file with mode: 0644]

index f115b67..e691f3a 100644 (file)
@@ -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()
@@ -479,6 +480,9 @@ 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);
@@ -553,20 +557,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 ++) {
index cc0aa1f..60c14b3 100644 (file)
@@ -197,6 +197,13 @@ TEST_F(FPDFViewEmbeddertest, Crasher_452455) {
   UnloadPage(page);
 }
 
-TEST_F(FPDFViewEmbeddertest, Crasher3) {
+TEST_F(FPDFViewEmbeddertest, Crasher_454695) {
   EXPECT_TRUE(OpenDocument("testing/resources/bug_454695.pdf"));
 }
+
+TEST_F(FPDFViewEmbeddertest, Crasher_471990) {
+  EXPECT_TRUE(OpenDocument("testing/resources/bug_471990.pdf"));
+  FPDF_PAGE page = LoadPage(0);
+  EXPECT_NE(nullptr, page);
+  UnloadPage(page);
+}
diff --git a/testing/resources/bug_471990.in b/testing/resources/bug_471990.in
new file mode 100644 (file)
index 0000000..7425405
--- /dev/null
@@ -0,0 +1,56 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Pages
+  /Kids [10 0 R]
+  /Count 1
+>>
+{{object 10 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Resources <<
+    /ColorSpace <<
+      /cs1 20 0 R
+    >>
+  >>
+  /Contents 30 0 R
+  /MediaBox [0 0 842 1191]
+  /CropBox [123.307 198.425 718.693 992.575]
+>>
+endobj
+{{object 20 0}} [
+  /Separation /All
+  /DeviceCMYK 21 0 R
+]
+endobj
+{{object 21 0}} <<
+  /FunctionType 0
+  /BitsPerSample 536870910
+  /Range [0 1 0 1 0 1 0 1]
+  /Decode [0 1 0 1 0 1 0 1]
+  /Length 1073741823
+  /Encode [0 1]
+  /Domain [0 1]
+  /Size [2]
+>>
+stream
+endstream
+endobj
+{{object 30 0}} <<
+>>
+stream
+/cs1 cs
+0 scn
+endstream
+endobj
+{{xref}}
+trailer <<
+  /Root 1 0 R
+  /Size 30
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/bug_471990.pdf b/testing/resources/bug_471990.pdf
new file mode 100644 (file)
index 0000000..8d8a3e2
--- /dev/null
@@ -0,0 +1,90 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+  /Type /Pages
+  /Kids [10 0 R]
+  /Count 1
+>>
+10 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Resources <<
+    /ColorSpace <<
+      /cs1 20 0 R
+    >>
+  >>
+  /Contents 30 0 R
+  /MediaBox [0 0 842 1191]
+  /CropBox [123.307 198.425 718.693 992.575]
+>>
+endobj
+20 0 obj [
+  /Separation /All
+  /DeviceCMYK 21 0 R
+]
+endobj
+21 0 obj <<
+  /FunctionType 0
+  /BitsPerSample 536870910
+  /Range [0 1 0 1 0 1 0 1]
+  /Decode [0 1 0 1 0 1 0 1]
+  /Length 1073741823
+  /Encode [0 1]
+  /Domain [0 1]
+  /Size [2]
+>>
+stream
+endstream
+endobj
+30 0 obj <<
+>>
+stream
+/cs1 cs
+0 scn
+endstream
+endobj
+xref
+0 31
+0000000000 65535 f 
+0000000015 00000 n 
+0000000068 00000 n 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000125 00000 n 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000333 00000 n 
+0000000393 00000 n 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000000 65535 f 
+0000000597 00000 n 
+trailer <<
+  /Root 1 0 R
+  /Size 30
+>>
+startxref
+650
+%%EOF