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)16pdfium::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)24CJBig2_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)30int32_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)52int32_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)74int32_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)83int32_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)92int32_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)101int32_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)111int32_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()120void CJBig2_BitStream::alignByte() { 121 if (m_dwBitIdx != 0) { 122 addOffset(1); 123 m_dwBitIdx = 0; 124 } 125 } 126 getCurByte() const127uint8_t CJBig2_BitStream::getCurByte() const { 128 return IsInBounds() ? m_Span[m_dwByteIdx] : 0; 129 } 130 incByteIdx()131void CJBig2_BitStream::incByteIdx() { 132 addOffset(1); 133 } 134 getCurByte_arith() const135uint8_t CJBig2_BitStream::getCurByte_arith() const { 136 return IsInBounds() ? m_Span[m_dwByteIdx] : 0xFF; 137 } 138 getNextByte_arith() const139uint8_t CJBig2_BitStream::getNextByte_arith() const { 140 return m_dwByteIdx + 1 < m_Span.size() ? m_Span[m_dwByteIdx + 1] : 0xFF; 141 } 142 getOffset() const143uint32_t CJBig2_BitStream::getOffset() const { 144 return m_dwByteIdx; 145 } 146 setOffset(uint32_t dwOffset)147void 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)152void 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() const160uint32_t CJBig2_BitStream::getBitPos() const { 161 return (m_dwByteIdx << 3) + m_dwBitIdx; 162 } 163 setBitPos(uint32_t dwBitPos)164void CJBig2_BitStream::setBitPos(uint32_t dwBitPos) { 165 m_dwByteIdx = dwBitPos >> 3; 166 m_dwBitIdx = dwBitPos & 7; 167 } 168 getPointer() const169const uint8_t* CJBig2_BitStream::getPointer() const { 170 return m_Span.subspan(m_dwByteIdx).data(); 171 } 172 getByteLeft() const173uint32_t CJBig2_BitStream::getByteLeft() const { 174 FX_SAFE_UINT32 result = getBufSpan().size(); 175 result -= m_dwByteIdx; 176 return result.ValueOrDie(); 177 } 178 AdvanceBit()179void CJBig2_BitStream::AdvanceBit() { 180 if (m_dwBitIdx == 7) { 181 ++m_dwByteIdx; 182 m_dwBitIdx = 0; 183 } else { 184 ++m_dwBitIdx; 185 } 186 } 187 IsInBounds() const188bool CJBig2_BitStream::IsInBounds() const { 189 return m_dwByteIdx < getBufSpan().size(); 190 } 191 LengthInBits() const192uint32_t CJBig2_BitStream::LengthInBits() const { 193 FX_SAFE_UINT32 result = getBufSpan().size(); 194 result *= 8; 195 return result.ValueOrDie(); 196 } 197