• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fxcodec/jbig2/JBig2_BitStream.h"
8 
9 #include <algorithm>
10 
11 #include "core/fxcrt/fx_safe_types.h"
12 #include "core/fxcrt/numerics/safe_conversions.h"
13 
14 namespace {
15 
ValidatedSpan(pdfium::span<const uint8_t> sp)16 pdfium::span<const uint8_t> ValidatedSpan(pdfium::span<const uint8_t> sp) {
17   if (sp.size() > 256 * 1024 * 1024)
18     return {};
19   return sp;
20 }
21 
22 }  // namespace
23 
CJBig2_BitStream(pdfium::span<const uint8_t> pSrcStream,uint64_t key)24 CJBig2_BitStream::CJBig2_BitStream(pdfium::span<const uint8_t> pSrcStream,
25                                    uint64_t key)
26     : m_Span(ValidatedSpan(pSrcStream)), m_Key(key) {}
27 
28 CJBig2_BitStream::~CJBig2_BitStream() = default;
29 
readNBits(uint32_t dwBits,uint32_t * dwResult)30 int32_t CJBig2_BitStream::readNBits(uint32_t dwBits, uint32_t* dwResult) {
31   if (!IsInBounds())
32     return -1;
33 
34   uint32_t dwBitPos = getBitPos();
35   if (dwBitPos > LengthInBits())
36     return -1;
37 
38   *dwResult = 0;
39   if (dwBitPos + dwBits <= LengthInBits())
40     dwBitPos = dwBits;
41   else
42     dwBitPos = LengthInBits() - dwBitPos;
43 
44   for (; dwBitPos > 0; --dwBitPos) {
45     *dwResult =
46         (*dwResult << 1) | ((m_Span[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01);
47     AdvanceBit();
48   }
49   return 0;
50 }
51 
readNBits(uint32_t dwBits,int32_t * nResult)52 int32_t CJBig2_BitStream::readNBits(uint32_t dwBits, int32_t* nResult) {
53   if (!IsInBounds())
54     return -1;
55 
56   uint32_t dwBitPos = getBitPos();
57   if (dwBitPos > LengthInBits())
58     return -1;
59 
60   *nResult = 0;
61   if (dwBitPos + dwBits <= LengthInBits())
62     dwBitPos = dwBits;
63   else
64     dwBitPos = LengthInBits() - dwBitPos;
65 
66   for (; dwBitPos > 0; --dwBitPos) {
67     *nResult =
68         (*nResult << 1) | ((m_Span[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01);
69     AdvanceBit();
70   }
71   return 0;
72 }
73 
read1Bit(uint32_t * dwResult)74 int32_t CJBig2_BitStream::read1Bit(uint32_t* dwResult) {
75   if (!IsInBounds())
76     return -1;
77 
78   *dwResult = (m_Span[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01;
79   AdvanceBit();
80   return 0;
81 }
82 
read1Bit(bool * bResult)83 int32_t CJBig2_BitStream::read1Bit(bool* bResult) {
84   if (!IsInBounds())
85     return -1;
86 
87   *bResult = (m_Span[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01;
88   AdvanceBit();
89   return 0;
90 }
91 
read1Byte(uint8_t * cResult)92 int32_t CJBig2_BitStream::read1Byte(uint8_t* cResult) {
93   if (!IsInBounds())
94     return -1;
95 
96   *cResult = m_Span[m_dwByteIdx];
97   ++m_dwByteIdx;
98   return 0;
99 }
100 
readInteger(uint32_t * dwResult)101 int32_t CJBig2_BitStream::readInteger(uint32_t* dwResult) {
102   if (m_dwByteIdx + 3 >= m_Span.size())
103     return -1;
104 
105   *dwResult = (m_Span[m_dwByteIdx] << 24) | (m_Span[m_dwByteIdx + 1] << 16) |
106               (m_Span[m_dwByteIdx + 2] << 8) | m_Span[m_dwByteIdx + 3];
107   m_dwByteIdx += 4;
108   return 0;
109 }
110 
readShortInteger(uint16_t * dwResult)111 int32_t CJBig2_BitStream::readShortInteger(uint16_t* dwResult) {
112   if (m_dwByteIdx + 1 >= m_Span.size())
113     return -1;
114 
115   *dwResult = (m_Span[m_dwByteIdx] << 8) | m_Span[m_dwByteIdx + 1];
116   m_dwByteIdx += 2;
117   return 0;
118 }
119 
alignByte()120 void CJBig2_BitStream::alignByte() {
121   if (m_dwBitIdx != 0) {
122     addOffset(1);
123     m_dwBitIdx = 0;
124   }
125 }
126 
getCurByte() const127 uint8_t CJBig2_BitStream::getCurByte() const {
128   return IsInBounds() ? m_Span[m_dwByteIdx] : 0;
129 }
130 
incByteIdx()131 void CJBig2_BitStream::incByteIdx() {
132   addOffset(1);
133 }
134 
getCurByte_arith() const135 uint8_t CJBig2_BitStream::getCurByte_arith() const {
136   return IsInBounds() ? m_Span[m_dwByteIdx] : 0xFF;
137 }
138 
getNextByte_arith() const139 uint8_t CJBig2_BitStream::getNextByte_arith() const {
140   return m_dwByteIdx + 1 < m_Span.size() ? m_Span[m_dwByteIdx + 1] : 0xFF;
141 }
142 
getOffset() const143 uint32_t CJBig2_BitStream::getOffset() const {
144   return m_dwByteIdx;
145 }
146 
setOffset(uint32_t dwOffset)147 void CJBig2_BitStream::setOffset(uint32_t dwOffset) {
148   m_dwByteIdx =
149       std::min(dwOffset, pdfium::checked_cast<uint32_t>(getBufSpan().size()));
150 }
151 
addOffset(uint32_t dwDelta)152 void CJBig2_BitStream::addOffset(uint32_t dwDelta) {
153   FX_SAFE_UINT32 new_offset = m_dwByteIdx;
154   new_offset += dwDelta;
155   if (new_offset.IsValid()) {
156     setOffset(new_offset.ValueOrDie());
157   }
158 }
159 
getBitPos() const160 uint32_t CJBig2_BitStream::getBitPos() const {
161   return (m_dwByteIdx << 3) + m_dwBitIdx;
162 }
163 
setBitPos(uint32_t dwBitPos)164 void CJBig2_BitStream::setBitPos(uint32_t dwBitPos) {
165   m_dwByteIdx = dwBitPos >> 3;
166   m_dwBitIdx = dwBitPos & 7;
167 }
168 
getPointer() const169 const uint8_t* CJBig2_BitStream::getPointer() const {
170   return m_Span.subspan(m_dwByteIdx).data();
171 }
172 
getByteLeft() const173 uint32_t CJBig2_BitStream::getByteLeft() const {
174   FX_SAFE_UINT32 result = getBufSpan().size();
175   result -= m_dwByteIdx;
176   return result.ValueOrDie();
177 }
178 
AdvanceBit()179 void CJBig2_BitStream::AdvanceBit() {
180   if (m_dwBitIdx == 7) {
181     ++m_dwByteIdx;
182     m_dwBitIdx = 0;
183   } else {
184     ++m_dwBitIdx;
185   }
186 }
187 
IsInBounds() const188 bool CJBig2_BitStream::IsInBounds() const {
189   return m_dwByteIdx < getBufSpan().size();
190 }
191 
LengthInBits() const192 uint32_t CJBig2_BitStream::LengthInBits() const {
193   FX_SAFE_UINT32 result = getBufSpan().size();
194   result *= 8;
195   return result.ValueOrDie();
196 }
197