Merge to M47: Clear decoders after the image decoder in the /Filter array.

During decoding, when an image decoder is encountered, any
subsequent decoders are ignored, but remain in the array. However,
later on CPDF_DIBSource::ValidateDictParam expects the image
decoder to be the last in the array, causing issues.

A check is also added in CPDF_DIBSource::GetScanline to ensure
that the calculated pitch value is <= the (4-aligned) pitch value in the
cached bitmap to prevent future issues.

Also cleans up some NULL usages.

BUG=552046

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

(cherry picked from commit 182d129bcee8f7731b9bbfde0064295ad3b37271)

R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1444503002 .
diff --git a/core/include/fpdfapi/fpdf_objects.h b/core/include/fpdfapi/fpdf_objects.h
index c2d838d..0778799 100644
--- a/core/include/fpdfapi/fpdf_objects.h
+++ b/core/include/fpdfapi/fpdf_objects.h
@@ -267,7 +267,7 @@
                 CPDF_Object* pObj,
                 CPDF_IndirectObjects* pObjs = NULL);
 
-  void RemoveAt(FX_DWORD index);
+  void RemoveAt(FX_DWORD index, int nCount = 1);
 
   void Add(CPDF_Object* pObj, CPDF_IndirectObjects* pObjs = NULL);
 
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp
index 2d6e9f3..1633314 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp
@@ -398,18 +398,23 @@
         return TRUE;
       }
       offset = RunLengthDecode(last_buf, last_size, new_buf, new_size);
+    } else if (decoder == FX_BSTRC("Crypt")) {
+      continue;
     } else {
+      // If we get here, assume it's an image decoder.
       if (decoder == FX_BSTRC("DCT")) {
         decoder = "DCTDecode";
       } else if (decoder == FX_BSTRC("CCF")) {
         decoder = "CCITTFaxDecode";
-      } else if (decoder == FX_BSTRC("Crypt")) {
-        continue;
       }
       ImageEncoding = decoder;
       pImageParms = pParam;
       dest_buf = (uint8_t*)last_buf;
       dest_size = last_size;
+      if (pDecoder->GetType() == PDFOBJ_ARRAY) {
+        CPDF_Array* pDecoders = reinterpret_cast<CPDF_Array*>(pDecoder);
+        pDecoders->RemoveAt(i + 1, pDecoders->GetCount() - i - 1);
+      }
       return TRUE;
     }
     if (last_buf != src_buf) {
@@ -423,7 +428,7 @@
     last_size = new_size;
   }
   ImageEncoding = "";
-  pImageParms = NULL;
+  pImageParms = nullptr;
   dest_buf = last_buf;
   dest_size = last_size;
   return TRUE;
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp
index e1e821c..7baa252 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp
@@ -464,15 +464,18 @@
   }
   return (CPDF_Array*)p;
 }
-void CPDF_Array::RemoveAt(FX_DWORD i) {
-  ASSERT(m_Type == PDFOBJ_ARRAY);
-  if (i >= (FX_DWORD)m_Objects.GetSize()) {
+void CPDF_Array::RemoveAt(FX_DWORD i, int nCount) {
+  if (i >= (FX_DWORD)m_Objects.GetSize())
     return;
+
+  if (nCount <= 0 || nCount > m_Objects.GetSize() - i)
+    return;
+
+  for (int j = 0; j < nCount; ++j) {
+    if (CPDF_Object* p = static_cast<CPDF_Object*>(m_Objects.GetAt(i + j)))
+      p->Release();
   }
-  CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
-  if (p)
-    p->Release();
-  m_Objects.RemoveAt(i);
+  m_Objects.RemoveAt(i, nCount);
 }
 void CPDF_Array::SetAt(FX_DWORD i,
                        CPDF_Object* pObj,
diff --git a/core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp b/core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp
index f1fbf41..17d5f88 100644
--- a/core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp
+++ b/core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp
@@ -1098,14 +1098,14 @@
 }
 const uint8_t* CPDF_DIBSource::GetScanline(int line) const {
   if (m_bpc == 0) {
-    return NULL;
+    return nullptr;
   }
   FX_SAFE_DWORD src_pitch = CalculatePitch8(m_bpc, m_nComponents, m_Width, 1);
   if (!src_pitch.IsValid())
-    return NULL;
+    return nullptr;
   FX_DWORD src_pitch_value = src_pitch.ValueOrDie();
-  const uint8_t* pSrcLine = NULL;
-  if (m_pCachedBitmap) {
+  const uint8_t* pSrcLine = nullptr;
+  if (m_pCachedBitmap && src_pitch_value <= m_pCachedBitmap->GetPitch()) {
     if (line >= m_pCachedBitmap->GetHeight()) {
       line = m_pCachedBitmap->GetHeight() - 1;
     }
@@ -1117,7 +1117,7 @@
       pSrcLine = m_pStreamAcc->GetData() + line * src_pitch_value;
     }
   }
-  if (pSrcLine == NULL) {
+  if (!pSrcLine) {
     uint8_t* pLineBuf = m_pMaskedLine ? m_pMaskedLine : m_pLineBuf;
     FXSYS_memset(pLineBuf, 0xFF, m_Pitch);
     return pLineBuf;