1// Copyright 2017 PDFium Authors. All rights reserved.
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/fxcodec/jbig2/JBig2_BitStream.h"
6
7#include <memory>
8#include <utility>
9
10#include "core/fpdfapi/parser/cpdf_stream_acc.h"
11#include "testing/gtest/include/gtest/gtest.h"
12#include "third_party/base/ptr_util.h"
13
14TEST(JBig2_BitStream, ReadNBits) {
15  std::unique_ptr<uint8_t, FxFreeDeleter> data(FX_Alloc(uint8_t, 1));
16  data.get()[0] = 0xb1;  // 10110001
17
18  auto in_stream = pdfium::MakeUnique<CPDF_Stream>(std::move(data), 1, nullptr);
19  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.get());
20  acc->LoadAllDataFiltered();
21
22  CJBig2_BitStream stream(acc);
23
24  uint32_t val1;
25  EXPECT_EQ(0, stream.readNBits(1, &val1));
26  EXPECT_EQ(1U, val1);
27
28  int32_t val2;
29  EXPECT_EQ(0, stream.readNBits(1, &val2));
30  EXPECT_EQ(0, val2);
31
32  EXPECT_EQ(0, stream.readNBits(2, &val2));
33  EXPECT_EQ(3, val2);
34
35  EXPECT_EQ(0, stream.readNBits(4, &val2));
36  EXPECT_EQ(1, val2);
37}
38
39TEST(JBig2_BitStream, ReadNBitsLargerThenData) {
40  std::unique_ptr<uint8_t, FxFreeDeleter> data(FX_Alloc(uint8_t, 1));
41  data.get()[0] = 0xb1;
42
43  auto in_stream = pdfium::MakeUnique<CPDF_Stream>(std::move(data), 1, nullptr);
44  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.get());
45  acc->LoadAllDataFiltered();
46
47  CJBig2_BitStream stream(acc);
48
49  uint32_t val1;
50  EXPECT_EQ(0, stream.readNBits(10, &val1));
51  EXPECT_EQ(0xb1U, val1);
52}
53
54TEST(JBig2_BitStream, ReadNBitsNullStream) {
55  auto in_stream = pdfium::MakeUnique<CPDF_Stream>(nullptr, 0, nullptr);
56  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.get());
57  acc->LoadAllDataFiltered();
58
59  CJBig2_BitStream stream(acc);
60
61  uint32_t val1;
62  EXPECT_EQ(-1, stream.readNBits(1, &val1));
63
64  int32_t val2;
65  EXPECT_EQ(-1, stream.readNBits(2, &val2));
66}
67
68TEST(JBig2_BitStream, ReadNBitsEmptyStream) {
69  std::unique_ptr<uint8_t, FxFreeDeleter> data(FX_Alloc(uint8_t, 1));
70
71  auto in_stream = pdfium::MakeUnique<CPDF_Stream>(std::move(data), 0, nullptr);
72  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.get());
73  acc->LoadAllDataFiltered();
74
75  CJBig2_BitStream stream(acc);
76
77  uint32_t val1;
78  EXPECT_EQ(-1, stream.readNBits(1, &val1));
79
80  int32_t val2;
81  EXPECT_EQ(-1, stream.readNBits(2, &val2));
82}
83
84TEST(JBig2_BitStream, ReadNBitsOutOfBounds) {
85  std::unique_ptr<uint8_t, FxFreeDeleter> data(FX_Alloc(uint8_t, 1));
86  data.get()[0] = 0xb1;  // 10110001
87
88  auto in_stream = pdfium::MakeUnique<CPDF_Stream>(std::move(data), 1, nullptr);
89  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.get());
90  acc->LoadAllDataFiltered();
91
92  CJBig2_BitStream stream(acc);
93
94  uint32_t val1;
95  EXPECT_EQ(0, stream.readNBits(8, &val1));
96
97  int32_t val2;
98  EXPECT_EQ(-1, stream.readNBits(2, &val2));
99}
100
101TEST(JBig2_BitStream, ReadNBitsWhereNIs36) {
102  std::unique_ptr<uint8_t, FxFreeDeleter> data(FX_Alloc(uint8_t, 5));
103  data.get()[0] = 0xb0;
104  data.get()[1] = 0x01;
105  data.get()[2] = 0x00;
106  data.get()[3] = 0x00;
107  data.get()[4] = 0x40;
108
109  auto in_stream = pdfium::MakeUnique<CPDF_Stream>(std::move(data), 5, nullptr);
110  auto acc = pdfium::MakeRetain<CPDF_StreamAcc>(in_stream.get());
111  acc->LoadAllDataFiltered();
112
113  CJBig2_BitStream stream(acc);
114
115  // This will shift off the top two bits and they end up lost.
116  uint32_t val1;
117  EXPECT_EQ(0, stream.readNBits(34, &val1));
118  EXPECT_EQ(0xc0040001U, val1);
119}
120