Use size_t for sizes in CFX_BitStream.

As would be flagged by -Wshorten-64-to-32

-- beef up some tests.

Change-Id: Iae5f29624ed47870e652eb09aa53debaf4503c78
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/86892
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcrt/cfx_bitstream.cpp b/core/fxcrt/cfx_bitstream.cpp
index 7b1e502..406552a 100644
--- a/core/fxcrt/cfx_bitstream.cpp
+++ b/core/fxcrt/cfx_bitstream.cpp
@@ -10,11 +10,11 @@
 
 #include "core/fxcrt/fx_memory.h"
 #include "core/fxcrt/fx_system.h"
-#include "third_party/base/check.h"
+#include "third_party/base/check_op.h"
 
 CFX_BitStream::CFX_BitStream(pdfium::span<const uint8_t> pData)
     : m_BitSize(pData.size() * 8), m_pData(pData.data()) {
-  DCHECK(pData.size() <= std::numeric_limits<uint32_t>::max() / 8);
+  CHECK_LE(pData.size(), std::numeric_limits<size_t>::max() / 8);
 }
 
 CFX_BitStream::~CFX_BitStream() = default;
@@ -30,12 +30,12 @@
     return 0;
 
   const uint32_t bit_pos = m_BitPos % 8;
-  uint32_t byte_pos = m_BitPos / 8;
+  size_t byte_pos = m_BitPos / 8;
   const uint8_t* data = m_pData.Get();
   uint8_t current_byte = data[byte_pos];
 
   if (nBits == 1) {
-    int bit = (current_byte & (1 << (7 - bit_pos))) ? 1 : 0;
+    uint32_t bit = (current_byte & (1 << (7 - bit_pos))) ? 1 : 0;
     m_BitPos++;
     return bit;
   }
diff --git a/core/fxcrt/cfx_bitstream.h b/core/fxcrt/cfx_bitstream.h
index 731a637..1b3cdd8 100644
--- a/core/fxcrt/cfx_bitstream.h
+++ b/core/fxcrt/cfx_bitstream.h
@@ -7,6 +7,7 @@
 #ifndef CORE_FXCRT_CFX_BITSTREAM_H_
 #define CORE_FXCRT_CFX_BITSTREAM_H_
 
+#include <stddef.h>
 #include <stdint.h>
 
 #include "core/fxcrt/unowned_ptr.h"
@@ -20,19 +21,19 @@
   void ByteAlign();
 
   bool IsEOF() const { return m_BitPos >= m_BitSize; }
-  uint32_t GetPos() const { return m_BitPos; }
+  size_t GetPos() const { return m_BitPos; }
   uint32_t GetBits(uint32_t nBits);
 
-  void SkipBits(uint32_t nBits) { m_BitPos += nBits; }
+  void SkipBits(size_t nBits) { m_BitPos += nBits; }
   void Rewind() { m_BitPos = 0; }
 
-  uint32_t BitsRemaining() const {
+  size_t BitsRemaining() const {
     return m_BitSize >= m_BitPos ? m_BitSize - m_BitPos : 0;
   }
 
  private:
-  uint32_t m_BitPos = 0;
-  const uint32_t m_BitSize;
+  size_t m_BitPos = 0;
+  const size_t m_BitSize;
   UnownedPtr<const uint8_t> const m_pData;
 };
 
diff --git a/core/fxcrt/cfx_bitstream_unittest.cpp b/core/fxcrt/cfx_bitstream_unittest.cpp
index 2ba3663..35688c4 100644
--- a/core/fxcrt/cfx_bitstream_unittest.cpp
+++ b/core/fxcrt/cfx_bitstream_unittest.cpp
@@ -3,6 +3,9 @@
 // found in the LICENSE file.
 
 #include "core/fxcrt/cfx_bitstream.h"
+
+#include <limits>
+
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -116,6 +119,63 @@
   EXPECT_TRUE(bitstream.IsEOF());
   EXPECT_EQ(1063U, bitstream.GetPos());
   EXPECT_EQ(0U, bitstream.BitsRemaining());
+  EXPECT_EQ(0u, bitstream.GetBits(4));
+
+  // Align past the end.
+  bitstream.ByteAlign();
+  EXPECT_TRUE(bitstream.IsEOF());
+  EXPECT_EQ(1064U, bitstream.GetPos());
+  EXPECT_EQ(0U, bitstream.BitsRemaining());
+  EXPECT_EQ(0u, bitstream.GetBits(4));
+}
+
+TEST(fxcrt, BitStreamEmpty) {
+  CFX_BitStream bitstream({});
+  EXPECT_TRUE(bitstream.IsEOF());
+  EXPECT_EQ(0U, bitstream.GetPos());
+  EXPECT_EQ(0U, bitstream.BitsRemaining());
+
+  // Getting bits returns zero and doesn't advance.
+  EXPECT_EQ(0u, bitstream.GetBits(4));
+  EXPECT_EQ(0U, bitstream.GetPos());
+
+  // Skip past the end.
+  bitstream.SkipBits(63);
+  EXPECT_TRUE(bitstream.IsEOF());
+  EXPECT_EQ(63U, bitstream.GetPos());
+  EXPECT_EQ(0U, bitstream.BitsRemaining());
+  EXPECT_EQ(0u, bitstream.GetBits(4));
+
+  // Align past the end.
+  bitstream.ByteAlign();
+  EXPECT_TRUE(bitstream.IsEOF());
+  EXPECT_EQ(64U, bitstream.GetPos());
+  EXPECT_EQ(0U, bitstream.BitsRemaining());
+  EXPECT_EQ(0u, bitstream.GetBits(4));
+}
+
+TEST(fxcrt, BitStreamBig) {
+  // We can't actually allocate enough memory to test the limits of
+  // the bitstream arithmetic, but as long as we don't try to extract
+  // any bits, the calculations should be unaffected.
+  constexpr size_t kAllocationBytes = std::numeric_limits<size_t>::max() / 8;
+  constexpr size_t kAllocationBits = kAllocationBytes * 8;
+  CFX_BitStream bitstream({nullptr, kAllocationBytes});
+  EXPECT_FALSE(bitstream.IsEOF());
+  EXPECT_EQ(0U, bitstream.GetPos());
+  EXPECT_EQ(kAllocationBits, bitstream.BitsRemaining());
+
+  // Skip some bits.
+  bitstream.SkipBits(kAllocationBits - 1023);
+  EXPECT_FALSE(bitstream.IsEOF());
+  EXPECT_EQ(kAllocationBits - 1023, bitstream.GetPos());
+  EXPECT_EQ(1023u, bitstream.BitsRemaining());
+
+  // Align to byte.
+  bitstream.ByteAlign();
+  EXPECT_FALSE(bitstream.IsEOF());
+  EXPECT_EQ(kAllocationBits - 1016, bitstream.GetPos());
+  EXPECT_EQ(1016u, bitstream.BitsRemaining());
 }
 
 TEST(fxcrt, BitStreamSameAsReferenceGetBits32) {