• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "core/fxcrt/cfx_bitstream.h"
6 
7 #include <limits>
8 
9 #include "core/fxcrt/compiler_specific.h"
10 #include "core/fxcrt/span.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 
13 namespace {
14 
ReferenceGetBits32(const uint8_t * pData,int bitpos,int nbits)15 uint32_t ReferenceGetBits32(const uint8_t* pData, int bitpos, int nbits) {
16   int result = 0;
17   UNSAFE_TODO({
18     for (int i = 0; i < nbits; i++) {
19       if (pData[(bitpos + i) / 8] & (1 << (7 - (bitpos + i) % 8))) {
20         result |= 1 << (nbits - i - 1);
21       }
22     }
23   });
24   return result;
25 }
26 
27 }  // namespace
28 
TEST(fxcrt,BitStream)29 TEST(fxcrt, BitStream) {
30   static const uint8_t kData[] = {0x00, 0x11, 0x22, 0x33,
31                                   0x44, 0x55, 0x66, 0x77};
32   CFX_BitStream bitstream(kData);
33 
34   // Initial state.
35   EXPECT_FALSE(bitstream.IsEOF());
36   EXPECT_EQ(0U, bitstream.GetPos());
37   EXPECT_EQ(64U, bitstream.BitsRemaining());
38 
39   // Read, read, read!
40   EXPECT_EQ(0x00U, bitstream.GetBits(8));
41   EXPECT_EQ(8U, bitstream.GetPos());
42   EXPECT_EQ(56U, bitstream.BitsRemaining());
43 
44   EXPECT_EQ(0x00U, bitstream.GetBits(1));
45   EXPECT_EQ(9U, bitstream.GetPos());
46   EXPECT_EQ(55U, bitstream.BitsRemaining());
47 
48   EXPECT_EQ(0x00U, bitstream.GetBits(2));
49   EXPECT_EQ(11U, bitstream.GetPos());
50   EXPECT_EQ(53U, bitstream.BitsRemaining());
51 
52   EXPECT_EQ(0x04U, bitstream.GetBits(3));
53   EXPECT_EQ(14U, bitstream.GetPos());
54   EXPECT_EQ(50U, bitstream.BitsRemaining());
55 
56   EXPECT_EQ(0x04U, bitstream.GetBits(4));
57   EXPECT_EQ(18U, bitstream.GetPos());
58   EXPECT_EQ(46U, bitstream.BitsRemaining());
59 
60   EXPECT_EQ(0x44U, bitstream.GetBits(7));
61   EXPECT_EQ(25U, bitstream.GetPos());
62   EXPECT_EQ(39U, bitstream.BitsRemaining());
63 
64   EXPECT_EQ(0xCDU, bitstream.GetBits(9));
65   EXPECT_EQ(34U, bitstream.GetPos());
66   EXPECT_EQ(30U, bitstream.BitsRemaining());
67 
68   EXPECT_EQ(0x08AAU, bitstream.GetBits(15));
69   EXPECT_EQ(49U, bitstream.GetPos());
70   EXPECT_EQ(15U, bitstream.BitsRemaining());
71 
72   // Cannot advance past the end.
73   EXPECT_EQ(0x00U, bitstream.GetBits(16));
74   EXPECT_EQ(49U, bitstream.GetPos());
75   EXPECT_EQ(15U, bitstream.BitsRemaining());
76 
77   // Make sure SkipBits() works.
78   bitstream.SkipBits(14);
79   EXPECT_EQ(63U, bitstream.GetPos());
80   EXPECT_EQ(1U, bitstream.BitsRemaining());
81   bitstream.SkipBits(2);
82   EXPECT_EQ(65U, bitstream.GetPos());
83   EXPECT_EQ(0U, bitstream.BitsRemaining());
84   EXPECT_TRUE(bitstream.IsEOF());
85 
86   // Make sure Rewind() works.
87   bitstream.Rewind();
88   EXPECT_FALSE(bitstream.IsEOF());
89   EXPECT_EQ(0U, bitstream.GetPos());
90   EXPECT_EQ(64U, bitstream.BitsRemaining());
91 
92   // Read some more.
93   bitstream.SkipBits(5);
94   EXPECT_EQ(5U, bitstream.GetPos());
95   EXPECT_EQ(59U, bitstream.BitsRemaining());
96 
97   EXPECT_EQ(0x0448U, bitstream.GetBits(17));
98   EXPECT_EQ(22U, bitstream.GetPos());
99   EXPECT_EQ(42U, bitstream.BitsRemaining());
100 
101   // Make sure ByteAlign() works.
102   bitstream.ByteAlign();
103   EXPECT_EQ(24U, bitstream.GetPos());
104   EXPECT_EQ(40U, bitstream.BitsRemaining());
105 
106   EXPECT_EQ(0x19A22AB3U, bitstream.GetBits(31));
107   EXPECT_EQ(55U, bitstream.GetPos());
108   EXPECT_EQ(9U, bitstream.BitsRemaining());
109 
110   // Do some bigger reads.
111   bitstream.Rewind();
112   EXPECT_EQ(0x112233U, bitstream.GetBits(32));
113   EXPECT_EQ(32U, bitstream.GetPos());
114   EXPECT_EQ(32U, bitstream.BitsRemaining());
115 
116   bitstream.Rewind();
117   bitstream.SkipBits(31);
118   EXPECT_EQ(0xA22AB33BU, bitstream.GetBits(32));
119   EXPECT_EQ(63U, bitstream.GetPos());
120   EXPECT_EQ(1U, bitstream.BitsRemaining());
121 
122   // Skip past the end.
123   bitstream.SkipBits(1000);
124   EXPECT_TRUE(bitstream.IsEOF());
125   EXPECT_EQ(1063U, bitstream.GetPos());
126   EXPECT_EQ(0U, bitstream.BitsRemaining());
127   EXPECT_EQ(0u, bitstream.GetBits(4));
128 
129   // Align past the end.
130   bitstream.ByteAlign();
131   EXPECT_TRUE(bitstream.IsEOF());
132   EXPECT_EQ(1064U, bitstream.GetPos());
133   EXPECT_EQ(0U, bitstream.BitsRemaining());
134   EXPECT_EQ(0u, bitstream.GetBits(4));
135 }
136 
TEST(fxcrt,BitStreamEmpty)137 TEST(fxcrt, BitStreamEmpty) {
138   CFX_BitStream bitstream({});
139   EXPECT_TRUE(bitstream.IsEOF());
140   EXPECT_EQ(0U, bitstream.GetPos());
141   EXPECT_EQ(0U, bitstream.BitsRemaining());
142 
143   // Getting bits returns zero and doesn't advance.
144   EXPECT_EQ(0u, bitstream.GetBits(4));
145   EXPECT_EQ(0U, bitstream.GetPos());
146 
147   // Skip past the end.
148   bitstream.SkipBits(63);
149   EXPECT_TRUE(bitstream.IsEOF());
150   EXPECT_EQ(63U, bitstream.GetPos());
151   EXPECT_EQ(0U, bitstream.BitsRemaining());
152   EXPECT_EQ(0u, bitstream.GetBits(4));
153 
154   // Align past the end.
155   bitstream.ByteAlign();
156   EXPECT_TRUE(bitstream.IsEOF());
157   EXPECT_EQ(64U, bitstream.GetPos());
158   EXPECT_EQ(0U, bitstream.BitsRemaining());
159   EXPECT_EQ(0u, bitstream.GetBits(4));
160 }
161 
TEST(fxcrt,BitStreamBig)162 TEST(fxcrt, BitStreamBig) {
163   // We can't actually allocate enough memory to test the limits of
164   // the bitstream arithmetic, but as long as we don't try to extract
165   // any bits, the calculations should be unaffected.
166   const uint8_t kNotReallyBigEnough[32] = {};
167   constexpr size_t kAllocationBytes = std::numeric_limits<size_t>::max() / 8;
168   constexpr size_t kAllocationBits = kAllocationBytes * 8;
169 
170   // SAFETY: intentionally not safe, see above.
171   CFX_BitStream bitstream(
172       UNSAFE_BUFFERS(pdfium::make_span(kNotReallyBigEnough, kAllocationBytes)));
173   EXPECT_FALSE(bitstream.IsEOF());
174   EXPECT_EQ(0U, bitstream.GetPos());
175   EXPECT_EQ(kAllocationBits, bitstream.BitsRemaining());
176 
177   // Skip some bits.
178   bitstream.SkipBits(kAllocationBits - 1023);
179   EXPECT_FALSE(bitstream.IsEOF());
180   EXPECT_EQ(kAllocationBits - 1023, bitstream.GetPos());
181   EXPECT_EQ(1023u, bitstream.BitsRemaining());
182 
183   // Align to byte.
184   bitstream.ByteAlign();
185   EXPECT_FALSE(bitstream.IsEOF());
186   EXPECT_EQ(kAllocationBits - 1016, bitstream.GetPos());
187   EXPECT_EQ(1016u, bitstream.BitsRemaining());
188 }
189 
TEST(fxcrt,BitStreamSameAsReferenceGetBits32)190 TEST(fxcrt, BitStreamSameAsReferenceGetBits32) {
191   static const unsigned char kData[] = {0xDE, 0x3F, 0xB1, 0x7C,
192                                         0x12, 0x9A, 0x04, 0x56};
193   CFX_BitStream bitstream(kData);
194   for (int nbits = 1; nbits <= 32; ++nbits) {
195     for (size_t bitpos = 0; bitpos < sizeof(kData) * 8 - nbits; ++bitpos) {
196       bitstream.Rewind();
197       bitstream.SkipBits(bitpos);
198       EXPECT_EQ(bitstream.GetBits(nbits),
199                 ReferenceGetBits32(kData, bitpos, nbits));
200     }
201   }
202 }
203