Implement CFX_CodecMemory.

This class is much simpler than CFX_MemoryStream and does only what
CFX_BmpDecompressor and CFX_GifContext needs. Swap out CFX_MemoryStream
and remove CFX_MemoryStream::Seek().

BUG=pdfium:263

Change-Id: Ifd8ce4d2b6c9fedd6ec842d46f54fc8e654fbca7
Reviewed-on: https://pdfium-review.googlesource.com/39880
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index c3576b4..4fbb293 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -824,6 +824,12 @@
       ]
       deps += [ "third_party:fx_tiff" ]
     }
+    if (pdf_enable_xfa_bmp || pdf_enable_xfa_gif) {
+      sources += [
+        "core/fxcodec/codec/cfx_codec_memory.cpp",
+        "core/fxcodec/codec/cfx_codec_memory.h",
+      ]
+    }
   }
 }
 
diff --git a/core/fxcodec/bmp/cfx_bmpdecompressor.cpp b/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
index c56d17d..739853a 100644
--- a/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
+++ b/core/fxcodec/bmp/cfx_bmpdecompressor.cpp
@@ -10,6 +10,7 @@
 #include <limits>
 
 #include "core/fxcodec/bmp/cfx_bmpcontext.h"
+#include "core/fxcrt/fx_safe_types.h"
 #include "core/fxcrt/fx_system.h"
 #include "third_party/base/logging.h"
 #include "third_party/base/numerics/safe_math.h"
@@ -659,8 +660,7 @@
 }
 
 void CFX_BmpDecompressor::SetInputBuffer(uint8_t* src_buf, uint32_t src_size) {
-  input_buffer_ =
-      pdfium::MakeRetain<CFX_MemoryStream>(src_buf, src_size, false);
+  input_buffer_ = pdfium::MakeRetain<CFX_CodecMemory>(src_buf, src_size);
 }
 
 FX_FILESIZE CFX_BmpDecompressor::GetAvailInput(uint8_t** avail_buf) {
diff --git a/core/fxcodec/bmp/cfx_bmpdecompressor.h b/core/fxcodec/bmp/cfx_bmpdecompressor.h
index 2f1585e..5192978 100644
--- a/core/fxcodec/bmp/cfx_bmpdecompressor.h
+++ b/core/fxcodec/bmp/cfx_bmpdecompressor.h
@@ -14,7 +14,7 @@
 #include <memory>
 #include <vector>
 
-#include "core/fxcrt/cfx_memorystream.h"
+#include "core/fxcodec/codec/cfx_codec_memory.h"
 
 class CFX_BmpContext;
 
@@ -69,7 +69,7 @@
   bool ValidateFlag() const;
   void SetHeight(int32_t signed_height);
 
-  RetainPtr<CFX_MemoryStream> input_buffer_;
+  RetainPtr<CFX_CodecMemory> input_buffer_;
 };
 
 #endif  // CORE_FXCODEC_BMP_CFX_BMPDECOMPRESSOR_H_
diff --git a/core/fxcodec/codec/cfx_codec_memory.cpp b/core/fxcodec/codec/cfx_codec_memory.cpp
new file mode 100644
index 0000000..8eac02c
--- /dev/null
+++ b/core/fxcodec/codec/cfx_codec_memory.cpp
@@ -0,0 +1,30 @@
+// Copyright 2018 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.
+
+#include "core/fxcodec/codec/cfx_codec_memory.h"
+
+#include <algorithm>
+
+CFX_CodecMemory::CFX_CodecMemory(uint8_t* buffer, size_t size)
+    : buffer_(buffer), size_(size) {}
+
+CFX_CodecMemory::~CFX_CodecMemory() = default;
+
+bool CFX_CodecMemory::Seek(size_t pos) {
+  if (pos > size_)
+    return false;
+
+  pos_ = pos;
+  return true;
+}
+
+size_t CFX_CodecMemory::ReadBlock(void* buffer, size_t size) {
+  if (!buffer || !size || IsEOF())
+    return 0;
+
+  size_t bytes_to_read = std::min(size, size_ - pos_);
+  memcpy(buffer, &buffer_[pos_], bytes_to_read);
+  pos_ += bytes_to_read;
+  return bytes_to_read;
+}
diff --git a/core/fxcodec/codec/cfx_codec_memory.h b/core/fxcodec/codec/cfx_codec_memory.h
new file mode 100644
index 0000000..6eee72a
--- /dev/null
+++ b/core/fxcodec/codec/cfx_codec_memory.h
@@ -0,0 +1,33 @@
+// Copyright 2018 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.
+
+#ifndef CORE_FXCODEC_CODEC_CFX_CODEC_MEMORY_H_
+#define CORE_FXCODEC_CODEC_CFX_CODEC_MEMORY_H_
+
+#include "core/fxcrt/retain_ptr.h"
+
+class CFX_CodecMemory : public Retainable {
+ public:
+  template <typename T, typename... Args>
+  friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
+
+  uint8_t* GetBuffer() { return buffer_; }
+  size_t GetSize() const { return size_; }
+  size_t GetPosition() const { return pos_; }
+  bool IsEOF() const { return pos_ >= size_; }
+  size_t ReadBlock(void* buffer, size_t size);
+
+  // Sets the cursor position to |pos| if possible.
+  bool Seek(size_t pos);
+
+ private:
+  CFX_CodecMemory(uint8_t* buffer, size_t size);
+  ~CFX_CodecMemory() override;
+
+  uint8_t* const buffer_;
+  const size_t size_;
+  size_t pos_ = 0;
+};
+
+#endif  // CORE_FXCODEC_CODEC_CFX_CODEC_MEMORY_H_
diff --git a/core/fxcodec/gif/cfx_gifcontext.cpp b/core/fxcodec/gif/cfx_gifcontext.cpp
index 44c2c65..4083072 100644
--- a/core/fxcodec/gif/cfx_gifcontext.cpp
+++ b/core/fxcodec/gif/cfx_gifcontext.cpp
@@ -343,8 +343,7 @@
 }
 
 void CFX_GifContext::SetInputBuffer(uint8_t* src_buf, uint32_t src_size) {
-  input_buffer_ =
-      pdfium::MakeRetain<CFX_MemoryStream>(src_buf, src_size, false);
+  input_buffer_ = pdfium::MakeRetain<CFX_CodecMemory>(src_buf, src_size);
 }
 
 uint32_t CFX_GifContext::GetAvailInput(uint8_t** avail_buf) const {
diff --git a/core/fxcodec/gif/cfx_gifcontext.h b/core/fxcodec/gif/cfx_gifcontext.h
index d9bcf49..f96cf05 100644
--- a/core/fxcodec/gif/cfx_gifcontext.h
+++ b/core/fxcodec/gif/cfx_gifcontext.h
@@ -11,9 +11,9 @@
 #include <vector>
 
 #include "core/fxcodec/codec/ccodec_gifmodule.h"
+#include "core/fxcodec/codec/cfx_codec_memory.h"
 #include "core/fxcodec/gif/cfx_gif.h"
 #include "core/fxcodec/gif/cfx_lzwdecompressor.h"
-#include "core/fxcrt/cfx_memorystream.h"
 #include "core/fxcrt/fx_string.h"
 #include "core/fxcrt/unowned_ptr.h"
 
@@ -66,7 +66,8 @@
   bool ReadData(uint8_t* dest, uint32_t size);
   CFX_GifDecodeStatus ReadGifSignature();
   CFX_GifDecodeStatus ReadLogicalScreenDescriptor();
-  RetainPtr<CFX_MemoryStream> input_buffer_;
+
+  RetainPtr<CFX_CodecMemory> input_buffer_;
 
  private:
   void SaveDecodingStatus(int32_t status);
diff --git a/core/fxcodec/gif/cfx_gifcontext_unittest.cpp b/core/fxcodec/gif/cfx_gifcontext_unittest.cpp
index 20aa691..d6cfa1f 100644
--- a/core/fxcodec/gif/cfx_gifcontext_unittest.cpp
+++ b/core/fxcodec/gif/cfx_gifcontext_unittest.cpp
@@ -18,7 +18,7 @@
   using CFX_GifContext::ReadGifSignature;
   using CFX_GifContext::ReadLogicalScreenDescriptor;
 
-  CFX_MemoryStream* InputBuffer() const { return input_buffer_.Get(); }
+  CFX_CodecMemory* InputBuffer() const { return input_buffer_.Get(); }
 };
 
 TEST(CFX_GifContext, SetInputBuffer) {
@@ -26,29 +26,29 @@
 
   context.SetInputBuffer(nullptr, 0);
   EXPECT_EQ(nullptr, context.InputBuffer()->GetBuffer());
-  EXPECT_EQ(0, context.InputBuffer()->GetSize());
-  EXPECT_EQ(0, context.InputBuffer()->GetPosition());
+  EXPECT_EQ(0u, context.InputBuffer()->GetSize());
+  EXPECT_EQ(0u, context.InputBuffer()->GetPosition());
 
   context.SetInputBuffer(nullptr, 100);
   EXPECT_EQ(nullptr, context.InputBuffer()->GetBuffer());
-  EXPECT_EQ(100, context.InputBuffer()->GetSize());
-  EXPECT_EQ(0, context.InputBuffer()->GetPosition());
+  EXPECT_EQ(100u, context.InputBuffer()->GetSize());
+  EXPECT_EQ(0u, context.InputBuffer()->GetPosition());
 
   uint8_t buffer[] = {0x00, 0x01, 0x02};
   context.SetInputBuffer(buffer, 0);
   EXPECT_EQ(buffer, context.InputBuffer()->GetBuffer());
-  EXPECT_EQ(0, context.InputBuffer()->GetSize());
-  EXPECT_EQ(0, context.InputBuffer()->GetPosition());
+  EXPECT_EQ(0u, context.InputBuffer()->GetSize());
+  EXPECT_EQ(0u, context.InputBuffer()->GetPosition());
 
   context.SetInputBuffer(buffer, 3);
   EXPECT_EQ(buffer, context.InputBuffer()->GetBuffer());
-  EXPECT_EQ(3, context.InputBuffer()->GetSize());
-  EXPECT_EQ(0, context.InputBuffer()->GetPosition());
+  EXPECT_EQ(3u, context.InputBuffer()->GetSize());
+  EXPECT_EQ(0u, context.InputBuffer()->GetPosition());
 
   context.SetInputBuffer(buffer, 100);
   EXPECT_EQ(buffer, context.InputBuffer()->GetBuffer());
-  EXPECT_EQ(100, context.InputBuffer()->GetSize());
-  EXPECT_EQ(0, context.InputBuffer()->GetPosition());
+  EXPECT_EQ(100u, context.InputBuffer()->GetSize());
+  EXPECT_EQ(0u, context.InputBuffer()->GetPosition());
 }
 
 TEST(CFX_GifContext, ReadData) {
@@ -70,7 +70,7 @@
 
   context.SetInputBuffer(src_buffer, 1);
   EXPECT_FALSE(context.ReadData(dest_buffer.data(), sizeof(src_buffer)));
-  EXPECT_EQ(0, context.InputBuffer()->GetPosition());
+  EXPECT_EQ(0u, context.InputBuffer()->GetPosition());
   EXPECT_FALSE(context.ReadData(nullptr, sizeof(src_buffer)));
   EXPECT_FALSE(context.ReadData(nullptr, 1));
   EXPECT_TRUE(context.ReadData(dest_buffer.data(), 1));
@@ -96,48 +96,48 @@
     uint8_t data[1];
     context.SetInputBuffer(data, 0);
     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadGifSignature());
-    EXPECT_EQ(0, context.InputBuffer()->GetPosition());
+    EXPECT_EQ(0u, context.InputBuffer()->GetPosition());
   }
   // Make sure testing the entire signature
   {
     uint8_t data[] = {'G', 'I', 'F'};
     context.SetInputBuffer(data, sizeof(data));
     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadGifSignature());
-    EXPECT_EQ(0, context.InputBuffer()->GetPosition());
+    EXPECT_EQ(0u, context.InputBuffer()->GetPosition());
   }
   {
     uint8_t data[] = {'N', 'O', 'T', 'G', 'I', 'F'};
     context.SetInputBuffer(data, sizeof(data));
     EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature());
-    EXPECT_EQ(6, context.InputBuffer()->GetPosition());
+    EXPECT_EQ(6u, context.InputBuffer()->GetPosition());
   }
   // Make sure not matching GIF8*a
   {
     uint8_t data[] = {'G', 'I', 'F', '8', '0', 'a'};
     context.SetInputBuffer(data, sizeof(data));
     EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature());
-    EXPECT_EQ(6, context.InputBuffer()->GetPosition());
+    EXPECT_EQ(6u, context.InputBuffer()->GetPosition());
   }
   // Make sure not matching GIF**a
   {
     uint8_t data[] = {'G', 'I', 'F', '9', '2', 'a'};
     context.SetInputBuffer(data, sizeof(data));
     EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature());
-    EXPECT_EQ(6, context.InputBuffer()->GetPosition());
+    EXPECT_EQ(6u, context.InputBuffer()->GetPosition());
   }
   // One valid signature
   {
     uint8_t data[] = {'G', 'I', 'F', '8', '7', 'a'};
     context.SetInputBuffer(data, sizeof(data));
     EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadGifSignature());
-    EXPECT_EQ(6, context.InputBuffer()->GetPosition());
+    EXPECT_EQ(6u, context.InputBuffer()->GetPosition());
   }
   // The other valid signature
   {
     uint8_t data[] = {'G', 'I', 'F', '8', '9', 'a'};
     context.SetInputBuffer(data, sizeof(data));
     EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadGifSignature());
-    EXPECT_EQ(6, context.InputBuffer()->GetPosition());
+    EXPECT_EQ(6u, context.InputBuffer()->GetPosition());
   }
 }
 
@@ -190,7 +190,7 @@
     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished,
               context.ReadLogicalScreenDescriptor());
 
-    EXPECT_EQ(0, context.InputBuffer()->GetPosition());
+    EXPECT_EQ(0u, context.InputBuffer()->GetPosition());
   }
   // LSD with global palette
   {
@@ -204,8 +204,7 @@
     EXPECT_EQ(CFX_GifDecodeStatus::Success,
               context.ReadLogicalScreenDescriptor());
 
-    EXPECT_EQ(sizeof(data),
-              static_cast<size_t>(context.InputBuffer()->GetPosition()));
+    EXPECT_EQ(sizeof(data), context.InputBuffer()->GetPosition());
     EXPECT_EQ(0x000A, context.width_);
     EXPECT_EQ(0x0F00, context.height_);
     EXPECT_EQ(1u, context.bc_index_);
@@ -214,8 +213,8 @@
     EXPECT_EQ(1u, context.global_pal_exp_);
     EXPECT_EQ(1, context.global_sort_flag_);
     EXPECT_EQ(2, context.global_color_resolution_);
-    EXPECT_TRUE(0 == memcmp(data.palette, context.global_palette_.data(),
-                            sizeof(data.palette)));
+    EXPECT_EQ(0, memcmp(data.palette, context.global_palette_.data(),
+                        sizeof(data.palette)));
   }
 }
 
@@ -232,8 +231,7 @@
 
     EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadHeader());
 
-    EXPECT_EQ(sizeof(data.signature),
-              static_cast<size_t>(context.InputBuffer()->GetPosition()));
+    EXPECT_EQ(sizeof(data.signature), context.InputBuffer()->GetPosition());
   }
   // Short after signature
   {
@@ -243,8 +241,7 @@
 
     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadHeader());
 
-    EXPECT_EQ(sizeof(signature),
-              static_cast<size_t>(context.InputBuffer()->GetPosition()));
+    EXPECT_EQ(sizeof(signature), context.InputBuffer()->GetPosition());
   }
   // Success without global palette
   {
@@ -257,8 +254,7 @@
 
     EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadHeader());
 
-    EXPECT_EQ(sizeof(data),
-              static_cast<size_t>(context.InputBuffer()->GetPosition()));
+    EXPECT_EQ(sizeof(data), context.InputBuffer()->GetPosition());
     EXPECT_EQ(0x000A, context.width_);
     EXPECT_EQ(0x0F00, context.height_);
     EXPECT_EQ(0u, context.bc_index_);  // bc_index_ is 0 if no global palette
@@ -275,8 +271,7 @@
 
     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadHeader());
 
-    EXPECT_EQ(sizeof(data.signature),
-              static_cast<size_t>(context.InputBuffer()->GetPosition()));
+    EXPECT_EQ(sizeof(data.signature), context.InputBuffer()->GetPosition());
   }
   // Success with global palette
   {
@@ -291,8 +286,7 @@
 
     EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadHeader());
 
-    EXPECT_EQ(sizeof(data),
-              static_cast<size_t>(context.InputBuffer()->GetPosition()));
+    EXPECT_EQ(sizeof(data), context.InputBuffer()->GetPosition());
     EXPECT_EQ(0x000A, context.width_);
     EXPECT_EQ(0x0F00, context.height_);
     EXPECT_EQ(1u, context.bc_index_);
@@ -300,7 +294,7 @@
     EXPECT_EQ(1u, context.global_pal_exp_);
     EXPECT_EQ(1, context.global_sort_flag_);
     EXPECT_EQ(2, context.global_color_resolution_);
-    EXPECT_TRUE(0 == memcmp(data.palette, context.global_palette_.data(),
-                            sizeof(data.palette)));
+    EXPECT_EQ(0, memcmp(data.palette, context.global_palette_.data(),
+                        sizeof(data.palette)));
   }
 }
diff --git a/core/fxcrt/cfx_memorystream.cpp b/core/fxcrt/cfx_memorystream.cpp
index 8073d37..15cde78 100644
--- a/core/fxcrt/cfx_memorystream.cpp
+++ b/core/fxcrt/cfx_memorystream.cpp
@@ -146,14 +146,6 @@
   return true;
 }
 
-bool CFX_MemoryStream::Seek(size_t pos) {
-  if (pos > m_nCurSize)
-    return false;
-
-  m_nCurPos = pos;
-  return true;
-}
-
 bool CFX_MemoryStream::ExpandBlocks(size_t size) {
   m_nCurSize = std::max(m_nCurSize, size);
   if (size <= m_nTotalSize)
diff --git a/core/fxcrt/cfx_memorystream.h b/core/fxcrt/cfx_memorystream.h
index 3726b89..cd89c62 100644
--- a/core/fxcrt/cfx_memorystream.h
+++ b/core/fxcrt/cfx_memorystream.h
@@ -26,9 +26,6 @@
   bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override;
   bool Flush() override;
 
-  // Sets the cursor position to |pos| if possible
-  bool Seek(size_t pos);
-
   uint8_t* GetBuffer() {
     return !m_Blocks.empty() ? m_Blocks.front() : nullptr;
   }