1 // Copyright 2014 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 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "core/fxcodec/jbig2/JBig2_Context.h" 8 9 #include <algorithm> 10 #include <limits> 11 #include <list> 12 #include <utility> 13 #include <vector> 14 15 #include "core/fpdfapi/parser/cpdf_stream.h" 16 #include "core/fpdfapi/parser/cpdf_stream_acc.h" 17 #include "core/fxcodec/jbig2/JBig2_ArithDecoder.h" 18 #include "core/fxcodec/jbig2/JBig2_BitStream.h" 19 #include "core/fxcodec/jbig2/JBig2_GrdProc.h" 20 #include "core/fxcodec/jbig2/JBig2_GrrdProc.h" 21 #include "core/fxcodec/jbig2/JBig2_HtrdProc.h" 22 #include "core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h" 23 #include "core/fxcodec/jbig2/JBig2_PddProc.h" 24 #include "core/fxcodec/jbig2/JBig2_SddProc.h" 25 #include "core/fxcodec/jbig2/JBig2_TrdProc.h" 26 #include "core/fxcrt/ifx_pauseindicator.h" 27 #include "third_party/base/ptr_util.h" 28 29 namespace { 30 GetHuffContextSize(uint8_t val)31 size_t GetHuffContextSize(uint8_t val) { 32 return val == 0 ? 65536 : val == 1 ? 8192 : 1024; 33 } 34 GetRefAggContextSize(bool val)35 size_t GetRefAggContextSize(bool val) { 36 return val ? 1024 : 8192; 37 } 38 39 } // namespace 40 41 // Implement a very small least recently used (LRU) cache. It is very 42 // common for a JBIG2 dictionary to span multiple pages in a PDF file, 43 // and we do not want to decode the same dictionary over and over 44 // again. We key off of the memory location of the dictionary. The 45 // list keeps track of the freshness of entries, with freshest ones 46 // at the front. Even a tiny cache size like 2 makes a dramatic 47 // difference for typical JBIG2 documents. 48 static const size_t kSymbolDictCacheMaxSize = 2; 49 static_assert(kSymbolDictCacheMaxSize > 0, 50 "Symbol Dictionary Cache must have non-zero size"); 51 CJBig2_Context(const RetainPtr<CPDF_StreamAcc> & pGlobalStream,const RetainPtr<CPDF_StreamAcc> & pSrcStream,std::list<CJBig2_CachePair> * pSymbolDictCache,bool bIsGlobal)52 CJBig2_Context::CJBig2_Context(const RetainPtr<CPDF_StreamAcc>& pGlobalStream, 53 const RetainPtr<CPDF_StreamAcc>& pSrcStream, 54 std::list<CJBig2_CachePair>* pSymbolDictCache, 55 bool bIsGlobal) 56 : m_nSegmentDecoded(0), 57 m_bInPage(false), 58 m_bBufSpecified(false), 59 m_PauseStep(10), 60 m_ProcessingStatus(FXCODEC_STATUS_FRAME_READY), 61 m_dwOffset(0), 62 m_pSymbolDictCache(pSymbolDictCache), 63 m_bIsGlobal(bIsGlobal) { 64 if (pGlobalStream && pGlobalStream->GetSize() > 0) { 65 m_pGlobalContext = pdfium::MakeUnique<CJBig2_Context>( 66 nullptr, pGlobalStream, pSymbolDictCache, true); 67 } 68 m_pStream = pdfium::MakeUnique<CJBig2_BitStream>(pSrcStream); 69 } 70 ~CJBig2_Context()71 CJBig2_Context::~CJBig2_Context() {} 72 decodeSequential(IFX_PauseIndicator * pPause)73 int32_t CJBig2_Context::decodeSequential(IFX_PauseIndicator* pPause) { 74 int32_t nRet; 75 if (m_pStream->getByteLeft() <= 0) 76 return JBIG2_END_OF_FILE; 77 78 while (m_pStream->getByteLeft() >= JBIG2_MIN_SEGMENT_SIZE) { 79 if (!m_pSegment) { 80 m_pSegment = pdfium::MakeUnique<CJBig2_Segment>(); 81 nRet = parseSegmentHeader(m_pSegment.get()); 82 if (nRet != JBIG2_SUCCESS) { 83 m_pSegment.reset(); 84 return nRet; 85 } 86 m_dwOffset = m_pStream->getOffset(); 87 } 88 nRet = parseSegmentData(m_pSegment.get(), pPause); 89 if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) { 90 m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE; 91 m_PauseStep = 2; 92 return JBIG2_SUCCESS; 93 } 94 if (nRet == JBIG2_END_OF_PAGE || nRet == JBIG2_END_OF_FILE) { 95 m_pSegment.reset(); 96 return JBIG2_SUCCESS; 97 } 98 if (nRet != JBIG2_SUCCESS) { 99 m_pSegment.reset(); 100 return nRet; 101 } 102 if (m_pSegment->m_dwData_length != 0xffffffff) { 103 m_dwOffset += m_pSegment->m_dwData_length; 104 if (!m_dwOffset.IsValid()) 105 return JBIG2_ERROR_FATAL; 106 107 m_pStream->setOffset(m_dwOffset.ValueOrDie()); 108 } else { 109 m_pStream->offset(4); 110 } 111 m_SegmentList.push_back(std::move(m_pSegment)); 112 if (m_pStream->getByteLeft() > 0 && m_pPage && pPause && 113 pPause->NeedToPauseNow()) { 114 m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE; 115 m_PauseStep = 2; 116 return JBIG2_SUCCESS; 117 } 118 } 119 return JBIG2_SUCCESS; 120 } 121 decodeRandomFirstPage(IFX_PauseIndicator * pPause)122 int32_t CJBig2_Context::decodeRandomFirstPage(IFX_PauseIndicator* pPause) { 123 int32_t nRet; 124 while (m_pStream->getByteLeft() > JBIG2_MIN_SEGMENT_SIZE) { 125 auto pSegment = pdfium::MakeUnique<CJBig2_Segment>(); 126 nRet = parseSegmentHeader(pSegment.get()); 127 if (nRet != JBIG2_SUCCESS) 128 return nRet; 129 130 if (pSegment->m_cFlags.s.type == 51) 131 break; 132 133 m_SegmentList.push_back(std::move(pSegment)); 134 if (pPause && pPause->NeedToPauseNow()) { 135 m_PauseStep = 3; 136 m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE; 137 return JBIG2_SUCCESS; 138 } 139 } 140 m_nSegmentDecoded = 0; 141 return decodeRandom(pPause); 142 } 143 decodeRandom(IFX_PauseIndicator * pPause)144 int32_t CJBig2_Context::decodeRandom(IFX_PauseIndicator* pPause) { 145 for (; m_nSegmentDecoded < m_SegmentList.size(); ++m_nSegmentDecoded) { 146 int32_t nRet = 147 parseSegmentData(m_SegmentList[m_nSegmentDecoded].get(), pPause); 148 if (nRet == JBIG2_END_OF_PAGE || nRet == JBIG2_END_OF_FILE) 149 return JBIG2_SUCCESS; 150 151 if (nRet != JBIG2_SUCCESS) 152 return nRet; 153 154 if (m_pPage && pPause && pPause->NeedToPauseNow()) { 155 m_PauseStep = 4; 156 m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE; 157 return JBIG2_SUCCESS; 158 } 159 } 160 return JBIG2_SUCCESS; 161 } 162 getFirstPage(uint8_t * pBuf,int32_t width,int32_t height,int32_t stride,IFX_PauseIndicator * pPause)163 int32_t CJBig2_Context::getFirstPage(uint8_t* pBuf, 164 int32_t width, 165 int32_t height, 166 int32_t stride, 167 IFX_PauseIndicator* pPause) { 168 int32_t nRet = 0; 169 if (m_pGlobalContext) { 170 nRet = m_pGlobalContext->decodeSequential(pPause); 171 if (nRet != JBIG2_SUCCESS) { 172 m_ProcessingStatus = FXCODEC_STATUS_ERROR; 173 return nRet; 174 } 175 } 176 m_PauseStep = 0; 177 m_pPage = pdfium::MakeUnique<CJBig2_Image>(width, height, stride, pBuf); 178 m_bBufSpecified = true; 179 if (pPause && pPause->NeedToPauseNow()) { 180 m_PauseStep = 1; 181 m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE; 182 return nRet; 183 } 184 return Continue(pPause); 185 } 186 Continue(IFX_PauseIndicator * pPause)187 int32_t CJBig2_Context::Continue(IFX_PauseIndicator* pPause) { 188 m_ProcessingStatus = FXCODEC_STATUS_DECODE_READY; 189 int32_t nRet = 0; 190 if (m_PauseStep <= 2) { 191 nRet = decodeSequential(pPause); 192 } else if (m_PauseStep == 3) { 193 nRet = decodeRandomFirstPage(pPause); 194 } else if (m_PauseStep == 4) { 195 nRet = decodeRandom(pPause); 196 } else if (m_PauseStep == 5) { 197 m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH; 198 return JBIG2_SUCCESS; 199 } 200 if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) 201 return nRet; 202 203 m_PauseStep = 5; 204 if (!m_bBufSpecified && nRet == JBIG2_SUCCESS) { 205 m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH; 206 return JBIG2_SUCCESS; 207 } 208 m_ProcessingStatus = nRet == JBIG2_SUCCESS ? FXCODEC_STATUS_DECODE_FINISH 209 : FXCODEC_STATUS_ERROR; 210 return nRet; 211 } 212 findSegmentByNumber(uint32_t dwNumber)213 CJBig2_Segment* CJBig2_Context::findSegmentByNumber(uint32_t dwNumber) { 214 if (m_pGlobalContext) { 215 CJBig2_Segment* pSeg = m_pGlobalContext->findSegmentByNumber(dwNumber); 216 if (pSeg) 217 return pSeg; 218 } 219 for (const auto& pSeg : m_SegmentList) { 220 if (pSeg->m_dwNumber == dwNumber) 221 return pSeg.get(); 222 } 223 return nullptr; 224 } 225 findReferredSegmentByTypeAndIndex(CJBig2_Segment * pSegment,uint8_t cType,int32_t nIndex)226 CJBig2_Segment* CJBig2_Context::findReferredSegmentByTypeAndIndex( 227 CJBig2_Segment* pSegment, 228 uint8_t cType, 229 int32_t nIndex) { 230 int32_t count = 0; 231 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { 232 CJBig2_Segment* pSeg = 233 findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]); 234 if (pSeg && pSeg->m_cFlags.s.type == cType) { 235 if (count == nIndex) 236 return pSeg; 237 ++count; 238 } 239 } 240 return nullptr; 241 } 242 parseSegmentHeader(CJBig2_Segment * pSegment)243 int32_t CJBig2_Context::parseSegmentHeader(CJBig2_Segment* pSegment) { 244 if (m_pStream->readInteger(&pSegment->m_dwNumber) != 0 || 245 m_pStream->read1Byte(&pSegment->m_cFlags.c) != 0) { 246 return JBIG2_ERROR_TOO_SHORT; 247 } 248 249 uint32_t dwTemp; 250 uint8_t cTemp = m_pStream->getCurByte(); 251 if ((cTemp >> 5) == 7) { 252 if (m_pStream->readInteger( 253 (uint32_t*)&pSegment->m_nReferred_to_segment_count) != 0) { 254 return JBIG2_ERROR_TOO_SHORT; 255 } 256 pSegment->m_nReferred_to_segment_count &= 0x1fffffff; 257 if (pSegment->m_nReferred_to_segment_count > 258 JBIG2_MAX_REFERRED_SEGMENT_COUNT) { 259 return JBIG2_ERROR_LIMIT; 260 } 261 dwTemp = 5 + 4 + (pSegment->m_nReferred_to_segment_count + 1) / 8; 262 } else { 263 if (m_pStream->read1Byte(&cTemp) != 0) 264 return JBIG2_ERROR_TOO_SHORT; 265 266 pSegment->m_nReferred_to_segment_count = cTemp >> 5; 267 dwTemp = 5 + 1; 268 } 269 uint8_t cSSize = 270 pSegment->m_dwNumber > 65536 ? 4 : pSegment->m_dwNumber > 256 ? 2 : 1; 271 uint8_t cPSize = pSegment->m_cFlags.s.page_association_size ? 4 : 1; 272 if (pSegment->m_nReferred_to_segment_count) { 273 pSegment->m_Referred_to_segment_numbers.resize( 274 pSegment->m_nReferred_to_segment_count); 275 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { 276 switch (cSSize) { 277 case 1: 278 if (m_pStream->read1Byte(&cTemp) != 0) 279 return JBIG2_ERROR_TOO_SHORT; 280 281 pSegment->m_Referred_to_segment_numbers[i] = cTemp; 282 break; 283 case 2: 284 uint16_t wTemp; 285 if (m_pStream->readShortInteger(&wTemp) != 0) 286 return JBIG2_ERROR_TOO_SHORT; 287 288 pSegment->m_Referred_to_segment_numbers[i] = wTemp; 289 break; 290 case 4: 291 if (m_pStream->readInteger(&dwTemp) != 0) 292 return JBIG2_ERROR_TOO_SHORT; 293 294 pSegment->m_Referred_to_segment_numbers[i] = dwTemp; 295 break; 296 } 297 if (pSegment->m_Referred_to_segment_numbers[i] >= pSegment->m_dwNumber) 298 return JBIG2_ERROR_TOO_SHORT; 299 } 300 } 301 if (cPSize == 1) { 302 if (m_pStream->read1Byte(&cTemp) != 0) 303 return JBIG2_ERROR_TOO_SHORT; 304 pSegment->m_dwPage_association = cTemp; 305 } else { 306 if (m_pStream->readInteger(&pSegment->m_dwPage_association) != 0) { 307 return JBIG2_ERROR_TOO_SHORT; 308 } 309 } 310 if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0) 311 return JBIG2_ERROR_TOO_SHORT; 312 313 pSegment->m_dwObjNum = m_pStream->getObjNum(); 314 pSegment->m_dwDataOffset = m_pStream->getOffset(); 315 pSegment->m_State = JBIG2_SEGMENT_DATA_UNPARSED; 316 return JBIG2_SUCCESS; 317 } 318 parseSegmentData(CJBig2_Segment * pSegment,IFX_PauseIndicator * pPause)319 int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment, 320 IFX_PauseIndicator* pPause) { 321 int32_t ret = ProcessingParseSegmentData(pSegment, pPause); 322 while (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE && 323 m_pStream->getByteLeft() > 0) { 324 ret = ProcessingParseSegmentData(pSegment, pPause); 325 } 326 return ret; 327 } 328 ProcessingParseSegmentData(CJBig2_Segment * pSegment,IFX_PauseIndicator * pPause)329 int32_t CJBig2_Context::ProcessingParseSegmentData(CJBig2_Segment* pSegment, 330 IFX_PauseIndicator* pPause) { 331 switch (pSegment->m_cFlags.s.type) { 332 case 0: 333 return parseSymbolDict(pSegment); 334 case 4: 335 case 6: 336 case 7: 337 if (!m_bInPage) 338 return JBIG2_ERROR_FATAL; 339 return parseTextRegion(pSegment); 340 case 16: 341 return parsePatternDict(pSegment, pPause); 342 case 20: 343 case 22: 344 case 23: 345 if (!m_bInPage) 346 return JBIG2_ERROR_FATAL; 347 return parseHalftoneRegion(pSegment, pPause); 348 case 36: 349 case 38: 350 case 39: 351 if (!m_bInPage) 352 return JBIG2_ERROR_FATAL; 353 return parseGenericRegion(pSegment, pPause); 354 case 40: 355 case 42: 356 case 43: 357 if (!m_bInPage) 358 return JBIG2_ERROR_FATAL; 359 return parseGenericRefinementRegion(pSegment); 360 case 48: { 361 uint16_t wTemp; 362 auto pPageInfo = pdfium::MakeUnique<JBig2PageInfo>(); 363 if (m_pStream->readInteger(&pPageInfo->m_dwWidth) != 0 || 364 m_pStream->readInteger(&pPageInfo->m_dwHeight) != 0 || 365 m_pStream->readInteger(&pPageInfo->m_dwResolutionX) != 0 || 366 m_pStream->readInteger(&pPageInfo->m_dwResolutionY) != 0 || 367 m_pStream->read1Byte(&pPageInfo->m_cFlags) != 0 || 368 m_pStream->readShortInteger(&wTemp) != 0) { 369 return JBIG2_ERROR_TOO_SHORT; 370 } 371 pPageInfo->m_bIsStriped = !!(wTemp & 0x8000); 372 pPageInfo->m_wMaxStripeSize = wTemp & 0x7fff; 373 bool bMaxHeight = (pPageInfo->m_dwHeight == 0xffffffff); 374 if (bMaxHeight && pPageInfo->m_bIsStriped != true) 375 pPageInfo->m_bIsStriped = true; 376 377 if (!m_bBufSpecified) { 378 uint32_t height = 379 bMaxHeight ? pPageInfo->m_wMaxStripeSize : pPageInfo->m_dwHeight; 380 m_pPage = 381 pdfium::MakeUnique<CJBig2_Image>(pPageInfo->m_dwWidth, height); 382 } 383 384 if (!m_pPage->data()) { 385 m_ProcessingStatus = FXCODEC_STATUS_ERROR; 386 return JBIG2_ERROR_TOO_SHORT; 387 } 388 389 m_pPage->fill((pPageInfo->m_cFlags & 4) ? 1 : 0); 390 m_PageInfoList.push_back(std::move(pPageInfo)); 391 m_bInPage = true; 392 } break; 393 case 49: 394 m_bInPage = false; 395 return JBIG2_END_OF_PAGE; 396 break; 397 case 50: 398 m_pStream->offset(pSegment->m_dwData_length); 399 break; 400 case 51: 401 return JBIG2_END_OF_FILE; 402 case 52: 403 m_pStream->offset(pSegment->m_dwData_length); 404 break; 405 case 53: 406 return parseTable(pSegment); 407 case 62: 408 m_pStream->offset(pSegment->m_dwData_length); 409 break; 410 default: 411 break; 412 } 413 return JBIG2_SUCCESS; 414 } 415 parseSymbolDict(CJBig2_Segment * pSegment)416 int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment) { 417 uint16_t wFlags; 418 if (m_pStream->readShortInteger(&wFlags) != 0) 419 return JBIG2_ERROR_TOO_SHORT; 420 421 auto pSymbolDictDecoder = pdfium::MakeUnique<CJBig2_SDDProc>(); 422 pSymbolDictDecoder->SDHUFF = wFlags & 0x0001; 423 pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001; 424 pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003; 425 pSymbolDictDecoder->SDRTEMPLATE = !!((wFlags >> 12) & 0x0003); 426 uint8_t cSDHUFFDH = (wFlags >> 2) & 0x0003; 427 uint8_t cSDHUFFDW = (wFlags >> 4) & 0x0003; 428 uint8_t cSDHUFFBMSIZE = (wFlags >> 6) & 0x0001; 429 uint8_t cSDHUFFAGGINST = (wFlags >> 7) & 0x0001; 430 if (pSymbolDictDecoder->SDHUFF == 0) { 431 const uint32_t dwTemp = (pSymbolDictDecoder->SDTEMPLATE == 0) ? 8 : 2; 432 for (uint32_t i = 0; i < dwTemp; ++i) { 433 if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDAT[i]) != 0) 434 return JBIG2_ERROR_TOO_SHORT; 435 } 436 } 437 if (pSymbolDictDecoder->SDREFAGG == 1 && !pSymbolDictDecoder->SDRTEMPLATE) { 438 for (int32_t i = 0; i < 4; ++i) { 439 if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDRAT[i]) != 0) 440 return JBIG2_ERROR_TOO_SHORT; 441 } 442 } 443 if (m_pStream->readInteger(&pSymbolDictDecoder->SDNUMEXSYMS) != 0 || 444 m_pStream->readInteger(&pSymbolDictDecoder->SDNUMNEWSYMS) != 0) { 445 return JBIG2_ERROR_TOO_SHORT; 446 } 447 if (pSymbolDictDecoder->SDNUMEXSYMS > JBIG2_MAX_EXPORT_SYSMBOLS || 448 pSymbolDictDecoder->SDNUMNEWSYMS > JBIG2_MAX_NEW_SYSMBOLS) { 449 return JBIG2_ERROR_LIMIT; 450 } 451 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { 452 if (!findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i])) 453 return JBIG2_ERROR_FATAL; 454 } 455 CJBig2_Segment* pLRSeg = nullptr; 456 pSymbolDictDecoder->SDNUMINSYMS = 0; 457 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { 458 CJBig2_Segment* pSeg = 459 findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]); 460 if (pSeg->m_cFlags.s.type == 0) { 461 pSymbolDictDecoder->SDNUMINSYMS += pSeg->m_SymbolDict->NumImages(); 462 pLRSeg = pSeg; 463 } 464 } 465 466 std::unique_ptr<CJBig2_Image*, FxFreeDeleter> SDINSYMS; 467 if (pSymbolDictDecoder->SDNUMINSYMS != 0) { 468 SDINSYMS.reset(FX_Alloc(CJBig2_Image*, pSymbolDictDecoder->SDNUMINSYMS)); 469 uint32_t dwTemp = 0; 470 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { 471 CJBig2_Segment* pSeg = 472 findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]); 473 if (pSeg->m_cFlags.s.type == 0) { 474 const CJBig2_SymbolDict& dict = *pSeg->m_SymbolDict.get(); 475 for (size_t j = 0; j < dict.NumImages(); ++j) 476 SDINSYMS.get()[dwTemp + j] = dict.GetImage(j); 477 dwTemp += dict.NumImages(); 478 } 479 } 480 } 481 pSymbolDictDecoder->SDINSYMS = SDINSYMS.get(); 482 483 std::unique_ptr<CJBig2_HuffmanTable> Table_B1; 484 std::unique_ptr<CJBig2_HuffmanTable> Table_B2; 485 std::unique_ptr<CJBig2_HuffmanTable> Table_B3; 486 std::unique_ptr<CJBig2_HuffmanTable> Table_B4; 487 std::unique_ptr<CJBig2_HuffmanTable> Table_B5; 488 if (pSymbolDictDecoder->SDHUFF == 1) { 489 if (cSDHUFFDH == 2 || cSDHUFFDW == 2) 490 return JBIG2_ERROR_FATAL; 491 492 int32_t nIndex = 0; 493 if (cSDHUFFDH == 0) { 494 Table_B4 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 495 HuffmanTable_B4, HuffmanTable_B4_Size, HuffmanTable_HTOOB_B4); 496 pSymbolDictDecoder->SDHUFFDH = Table_B4.get(); 497 } else if (cSDHUFFDH == 1) { 498 Table_B5 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 499 HuffmanTable_B5, HuffmanTable_B5_Size, HuffmanTable_HTOOB_B5); 500 pSymbolDictDecoder->SDHUFFDH = Table_B5.get(); 501 } else { 502 CJBig2_Segment* pSeg = 503 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); 504 if (!pSeg) 505 return JBIG2_ERROR_FATAL; 506 pSymbolDictDecoder->SDHUFFDH = pSeg->m_HuffmanTable.get(); 507 } 508 if (cSDHUFFDW == 0) { 509 Table_B2 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 510 HuffmanTable_B2, HuffmanTable_B2_Size, HuffmanTable_HTOOB_B2); 511 pSymbolDictDecoder->SDHUFFDW = Table_B2.get(); 512 } else if (cSDHUFFDW == 1) { 513 Table_B3 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 514 HuffmanTable_B3, HuffmanTable_B3_Size, HuffmanTable_HTOOB_B3); 515 pSymbolDictDecoder->SDHUFFDW = Table_B3.get(); 516 } else { 517 CJBig2_Segment* pSeg = 518 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); 519 if (!pSeg) 520 return JBIG2_ERROR_FATAL; 521 pSymbolDictDecoder->SDHUFFDW = pSeg->m_HuffmanTable.get(); 522 } 523 if (cSDHUFFBMSIZE == 0) { 524 Table_B1 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 525 HuffmanTable_B1, HuffmanTable_B1_Size, HuffmanTable_HTOOB_B1); 526 pSymbolDictDecoder->SDHUFFBMSIZE = Table_B1.get(); 527 } else { 528 CJBig2_Segment* pSeg = 529 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); 530 if (!pSeg) 531 return JBIG2_ERROR_FATAL; 532 pSymbolDictDecoder->SDHUFFBMSIZE = pSeg->m_HuffmanTable.get(); 533 } 534 if (pSymbolDictDecoder->SDREFAGG == 1) { 535 if (cSDHUFFAGGINST == 0) { 536 if (!Table_B1) { 537 Table_B1 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 538 HuffmanTable_B1, HuffmanTable_B1_Size, HuffmanTable_HTOOB_B1); 539 } 540 pSymbolDictDecoder->SDHUFFAGGINST = Table_B1.get(); 541 } else { 542 CJBig2_Segment* pSeg = 543 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); 544 if (!pSeg) 545 return JBIG2_ERROR_FATAL; 546 pSymbolDictDecoder->SDHUFFAGGINST = pSeg->m_HuffmanTable.get(); 547 } 548 } 549 } 550 551 const bool bUseGbContext = (pSymbolDictDecoder->SDHUFF == 0); 552 const bool bUseGrContext = (pSymbolDictDecoder->SDREFAGG == 1); 553 const size_t gbContextSize = 554 GetHuffContextSize(pSymbolDictDecoder->SDTEMPLATE); 555 const size_t grContextSize = 556 GetRefAggContextSize(pSymbolDictDecoder->SDRTEMPLATE); 557 std::vector<JBig2ArithCtx> gbContext; 558 std::vector<JBig2ArithCtx> grContext; 559 if ((wFlags & 0x0100) && pLRSeg) { 560 if (bUseGbContext) { 561 gbContext = pLRSeg->m_SymbolDict->GbContext(); 562 if (gbContext.size() != gbContextSize) 563 return JBIG2_ERROR_FATAL; 564 } 565 if (bUseGrContext) { 566 grContext = pLRSeg->m_SymbolDict->GrContext(); 567 if (grContext.size() != grContextSize) 568 return JBIG2_ERROR_FATAL; 569 } 570 } else { 571 if (bUseGbContext) 572 gbContext.resize(gbContextSize); 573 if (bUseGrContext) 574 grContext.resize(grContextSize); 575 } 576 577 CJBig2_CacheKey key = 578 CJBig2_CacheKey(pSegment->m_dwObjNum, pSegment->m_dwDataOffset); 579 bool cache_hit = false; 580 pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER; 581 if (m_bIsGlobal && key.first != 0) { 582 for (auto it = m_pSymbolDictCache->begin(); it != m_pSymbolDictCache->end(); 583 ++it) { 584 if (it->first == key) { 585 pSegment->m_SymbolDict = it->second->DeepCopy(); 586 m_pSymbolDictCache->push_front( 587 CJBig2_CachePair(key, std::move(it->second))); 588 m_pSymbolDictCache->erase(it); 589 cache_hit = true; 590 break; 591 } 592 } 593 } 594 if (!cache_hit) { 595 if (bUseGbContext) { 596 auto pArithDecoder = 597 pdfium::MakeUnique<CJBig2_ArithDecoder>(m_pStream.get()); 598 pSegment->m_SymbolDict = pSymbolDictDecoder->decode_Arith( 599 pArithDecoder.get(), &gbContext, &grContext); 600 if (!pSegment->m_SymbolDict) 601 return JBIG2_ERROR_FATAL; 602 603 m_pStream->alignByte(); 604 m_pStream->offset(2); 605 } else { 606 pSegment->m_SymbolDict = pSymbolDictDecoder->decode_Huffman( 607 m_pStream.get(), &gbContext, &grContext); 608 if (!pSegment->m_SymbolDict) 609 return JBIG2_ERROR_FATAL; 610 m_pStream->alignByte(); 611 } 612 if (m_bIsGlobal) { 613 std::unique_ptr<CJBig2_SymbolDict> value = 614 pSegment->m_SymbolDict->DeepCopy(); 615 size_t size = m_pSymbolDictCache->size(); 616 while (size >= kSymbolDictCacheMaxSize) { 617 m_pSymbolDictCache->pop_back(); 618 --size; 619 } 620 m_pSymbolDictCache->push_front(CJBig2_CachePair(key, std::move(value))); 621 } 622 } 623 if (wFlags & 0x0200) { 624 if (bUseGbContext) 625 pSegment->m_SymbolDict->SetGbContext(gbContext); 626 if (bUseGrContext) 627 pSegment->m_SymbolDict->SetGrContext(grContext); 628 } 629 return JBIG2_SUCCESS; 630 } 631 parseTextRegion(CJBig2_Segment * pSegment)632 int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { 633 uint16_t wFlags; 634 JBig2RegionInfo ri; 635 if (parseRegionInfo(&ri) != JBIG2_SUCCESS || 636 m_pStream->readShortInteger(&wFlags) != 0) { 637 return JBIG2_ERROR_TOO_SHORT; 638 } 639 640 auto pTRD = pdfium::MakeUnique<CJBig2_TRDProc>(); 641 pTRD->SBW = ri.width; 642 pTRD->SBH = ri.height; 643 pTRD->SBHUFF = wFlags & 0x0001; 644 pTRD->SBREFINE = (wFlags >> 1) & 0x0001; 645 uint32_t dwTemp = (wFlags >> 2) & 0x0003; 646 pTRD->SBSTRIPS = 1 << dwTemp; 647 pTRD->REFCORNER = (JBig2Corner)((wFlags >> 4) & 0x0003); 648 pTRD->TRANSPOSED = (wFlags >> 6) & 0x0001; 649 pTRD->SBCOMBOP = (JBig2ComposeOp)((wFlags >> 7) & 0x0003); 650 pTRD->SBDEFPIXEL = (wFlags >> 9) & 0x0001; 651 pTRD->SBDSOFFSET = (wFlags >> 10) & 0x001f; 652 if (pTRD->SBDSOFFSET >= 0x0010) { 653 pTRD->SBDSOFFSET = pTRD->SBDSOFFSET - 0x0020; 654 } 655 pTRD->SBRTEMPLATE = !!((wFlags >> 15) & 0x0001); 656 657 uint8_t cSBHUFFFS = 0; 658 uint8_t cSBHUFFDS = 0; 659 uint8_t cSBHUFFDT = 0; 660 uint8_t cSBHUFFRDW = 0; 661 uint8_t cSBHUFFRDH = 0; 662 uint8_t cSBHUFFRDX = 0; 663 uint8_t cSBHUFFRDY = 0; 664 uint8_t cSBHUFFRSIZE = 0; 665 if (pTRD->SBHUFF == 1) { 666 if (m_pStream->readShortInteger(&wFlags) != 0) 667 return JBIG2_ERROR_TOO_SHORT; 668 669 cSBHUFFFS = wFlags & 0x0003; 670 cSBHUFFDS = (wFlags >> 2) & 0x0003; 671 cSBHUFFDT = (wFlags >> 4) & 0x0003; 672 cSBHUFFRDW = (wFlags >> 6) & 0x0003; 673 cSBHUFFRDH = (wFlags >> 8) & 0x0003; 674 cSBHUFFRDX = (wFlags >> 10) & 0x0003; 675 cSBHUFFRDY = (wFlags >> 12) & 0x0003; 676 cSBHUFFRSIZE = (wFlags >> 14) & 0x0001; 677 } 678 if (pTRD->SBREFINE == 1 && !pTRD->SBRTEMPLATE) { 679 for (int32_t i = 0; i < 4; ++i) { 680 if (m_pStream->read1Byte((uint8_t*)&pTRD->SBRAT[i]) != 0) 681 return JBIG2_ERROR_TOO_SHORT; 682 } 683 } 684 if (m_pStream->readInteger(&pTRD->SBNUMINSTANCES) != 0) 685 return JBIG2_ERROR_TOO_SHORT; 686 687 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { 688 if (!findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i])) 689 return JBIG2_ERROR_FATAL; 690 } 691 692 pTRD->SBNUMSYMS = 0; 693 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { 694 CJBig2_Segment* pSeg = 695 findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]); 696 if (pSeg->m_cFlags.s.type == 0) { 697 pTRD->SBNUMSYMS += pSeg->m_SymbolDict->NumImages(); 698 } 699 } 700 701 std::unique_ptr<CJBig2_Image*, FxFreeDeleter> SBSYMS; 702 if (pTRD->SBNUMSYMS > 0) { 703 SBSYMS.reset(FX_Alloc(CJBig2_Image*, pTRD->SBNUMSYMS)); 704 dwTemp = 0; 705 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { 706 CJBig2_Segment* pSeg = 707 findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]); 708 if (pSeg->m_cFlags.s.type == 0) { 709 const CJBig2_SymbolDict& dict = *pSeg->m_SymbolDict.get(); 710 for (size_t j = 0; j < dict.NumImages(); ++j) 711 SBSYMS.get()[dwTemp + j] = dict.GetImage(j); 712 dwTemp += dict.NumImages(); 713 } 714 } 715 pTRD->SBSYMS = SBSYMS.get(); 716 } else { 717 pTRD->SBSYMS = nullptr; 718 } 719 720 if (pTRD->SBHUFF == 1) { 721 std::vector<JBig2HuffmanCode> SBSYMCODES = 722 decodeSymbolIDHuffmanTable(m_pStream.get(), pTRD->SBNUMSYMS); 723 if (SBSYMCODES.empty()) 724 return JBIG2_ERROR_FATAL; 725 726 m_pStream->alignByte(); 727 pTRD->SBSYMCODES = std::move(SBSYMCODES); 728 } else { 729 dwTemp = 0; 730 while ((uint32_t)(1 << dwTemp) < pTRD->SBNUMSYMS) { 731 ++dwTemp; 732 } 733 pTRD->SBSYMCODELEN = (uint8_t)dwTemp; 734 } 735 736 std::unique_ptr<CJBig2_HuffmanTable> Table_B1; 737 std::unique_ptr<CJBig2_HuffmanTable> Table_B6; 738 std::unique_ptr<CJBig2_HuffmanTable> Table_B7; 739 std::unique_ptr<CJBig2_HuffmanTable> Table_B8; 740 std::unique_ptr<CJBig2_HuffmanTable> Table_B9; 741 std::unique_ptr<CJBig2_HuffmanTable> Table_B10; 742 std::unique_ptr<CJBig2_HuffmanTable> Table_B11; 743 std::unique_ptr<CJBig2_HuffmanTable> Table_B12; 744 std::unique_ptr<CJBig2_HuffmanTable> Table_B13; 745 std::unique_ptr<CJBig2_HuffmanTable> Table_B14; 746 std::unique_ptr<CJBig2_HuffmanTable> Table_B15; 747 if (pTRD->SBHUFF == 1) { 748 if (cSBHUFFFS == 2 || cSBHUFFRDW == 2 || cSBHUFFRDH == 2 || 749 cSBHUFFRDX == 2 || cSBHUFFRDY == 2) { 750 return JBIG2_ERROR_FATAL; 751 } 752 int32_t nIndex = 0; 753 if (cSBHUFFFS == 0) { 754 Table_B6 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 755 HuffmanTable_B6, HuffmanTable_B6_Size, HuffmanTable_HTOOB_B6); 756 pTRD->SBHUFFFS = Table_B6.get(); 757 } else if (cSBHUFFFS == 1) { 758 Table_B7 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 759 HuffmanTable_B7, HuffmanTable_B7_Size, HuffmanTable_HTOOB_B7); 760 pTRD->SBHUFFFS = Table_B7.get(); 761 } else { 762 CJBig2_Segment* pSeg = 763 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); 764 if (!pSeg) 765 return JBIG2_ERROR_FATAL; 766 pTRD->SBHUFFFS = pSeg->m_HuffmanTable.get(); 767 } 768 if (cSBHUFFDS == 0) { 769 Table_B8 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 770 HuffmanTable_B8, HuffmanTable_B8_Size, HuffmanTable_HTOOB_B8); 771 pTRD->SBHUFFDS = Table_B8.get(); 772 } else if (cSBHUFFDS == 1) { 773 Table_B9 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 774 HuffmanTable_B9, HuffmanTable_B9_Size, HuffmanTable_HTOOB_B9); 775 pTRD->SBHUFFDS = Table_B9.get(); 776 } else if (cSBHUFFDS == 2) { 777 Table_B10 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 778 HuffmanTable_B10, HuffmanTable_B10_Size, HuffmanTable_HTOOB_B10); 779 pTRD->SBHUFFDS = Table_B10.get(); 780 } else { 781 CJBig2_Segment* pSeg = 782 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); 783 if (!pSeg) 784 return JBIG2_ERROR_FATAL; 785 pTRD->SBHUFFDS = pSeg->m_HuffmanTable.get(); 786 } 787 if (cSBHUFFDT == 0) { 788 Table_B11 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 789 HuffmanTable_B11, HuffmanTable_B11_Size, HuffmanTable_HTOOB_B11); 790 pTRD->SBHUFFDT = Table_B11.get(); 791 } else if (cSBHUFFDT == 1) { 792 Table_B12 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 793 HuffmanTable_B12, HuffmanTable_B12_Size, HuffmanTable_HTOOB_B12); 794 pTRD->SBHUFFDT = Table_B12.get(); 795 } else if (cSBHUFFDT == 2) { 796 Table_B13 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 797 HuffmanTable_B13, HuffmanTable_B13_Size, HuffmanTable_HTOOB_B13); 798 pTRD->SBHUFFDT = Table_B13.get(); 799 } else { 800 CJBig2_Segment* pSeg = 801 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); 802 if (!pSeg) 803 return JBIG2_ERROR_FATAL; 804 pTRD->SBHUFFDT = pSeg->m_HuffmanTable.get(); 805 } 806 if (cSBHUFFRDW == 0) { 807 Table_B14 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 808 HuffmanTable_B14, HuffmanTable_B14_Size, HuffmanTable_HTOOB_B14); 809 pTRD->SBHUFFRDW = Table_B14.get(); 810 } else if (cSBHUFFRDW == 1) { 811 Table_B15 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 812 HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15); 813 pTRD->SBHUFFRDW = Table_B15.get(); 814 } else { 815 CJBig2_Segment* pSeg = 816 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); 817 if (!pSeg) 818 return JBIG2_ERROR_FATAL; 819 pTRD->SBHUFFRDW = pSeg->m_HuffmanTable.get(); 820 } 821 if (cSBHUFFRDH == 0) { 822 if (!Table_B14) { 823 Table_B14 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 824 HuffmanTable_B14, HuffmanTable_B14_Size, HuffmanTable_HTOOB_B14); 825 } 826 pTRD->SBHUFFRDH = Table_B14.get(); 827 } else if (cSBHUFFRDH == 1) { 828 if (!Table_B15) { 829 Table_B15 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 830 HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15); 831 } 832 pTRD->SBHUFFRDH = Table_B15.get(); 833 } else { 834 CJBig2_Segment* pSeg = 835 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); 836 if (!pSeg) 837 return JBIG2_ERROR_FATAL; 838 pTRD->SBHUFFRDH = pSeg->m_HuffmanTable.get(); 839 } 840 if (cSBHUFFRDX == 0) { 841 if (!Table_B14) { 842 Table_B14 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 843 HuffmanTable_B14, HuffmanTable_B14_Size, HuffmanTable_HTOOB_B14); 844 } 845 pTRD->SBHUFFRDX = Table_B14.get(); 846 } else if (cSBHUFFRDX == 1) { 847 if (!Table_B15) { 848 Table_B15 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 849 HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15); 850 } 851 pTRD->SBHUFFRDX = Table_B15.get(); 852 } else { 853 CJBig2_Segment* pSeg = 854 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); 855 if (!pSeg) 856 return JBIG2_ERROR_FATAL; 857 pTRD->SBHUFFRDX = pSeg->m_HuffmanTable.get(); 858 } 859 if (cSBHUFFRDY == 0) { 860 if (!Table_B14) { 861 Table_B14 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 862 HuffmanTable_B14, HuffmanTable_B14_Size, HuffmanTable_HTOOB_B14); 863 } 864 pTRD->SBHUFFRDY = Table_B14.get(); 865 } else if (cSBHUFFRDY == 1) { 866 if (!Table_B15) { 867 Table_B15 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 868 HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15); 869 } 870 pTRD->SBHUFFRDY = Table_B15.get(); 871 } else { 872 CJBig2_Segment* pSeg = 873 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); 874 if (!pSeg) 875 return JBIG2_ERROR_FATAL; 876 pTRD->SBHUFFRDY = pSeg->m_HuffmanTable.get(); 877 } 878 if (cSBHUFFRSIZE == 0) { 879 Table_B1 = pdfium::MakeUnique<CJBig2_HuffmanTable>( 880 HuffmanTable_B1, HuffmanTable_B1_Size, HuffmanTable_HTOOB_B1); 881 pTRD->SBHUFFRSIZE = Table_B1.get(); 882 } else { 883 CJBig2_Segment* pSeg = 884 findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++); 885 if (!pSeg) 886 return JBIG2_ERROR_FATAL; 887 pTRD->SBHUFFRSIZE = pSeg->m_HuffmanTable.get(); 888 } 889 } 890 std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> grContext; 891 if (pTRD->SBREFINE == 1) { 892 const size_t size = GetRefAggContextSize(pTRD->SBRTEMPLATE); 893 grContext.reset(FX_Alloc(JBig2ArithCtx, size)); 894 JBIG2_memset(grContext.get(), 0, sizeof(JBig2ArithCtx) * size); 895 } 896 if (pTRD->SBHUFF == 0) { 897 auto pArithDecoder = 898 pdfium::MakeUnique<CJBig2_ArithDecoder>(m_pStream.get()); 899 pSegment->m_nResultType = JBIG2_IMAGE_POINTER; 900 pSegment->m_Image = 901 pTRD->decode_Arith(pArithDecoder.get(), grContext.get(), nullptr); 902 if (!pSegment->m_Image) 903 return JBIG2_ERROR_FATAL; 904 m_pStream->alignByte(); 905 m_pStream->offset(2); 906 } else { 907 pSegment->m_nResultType = JBIG2_IMAGE_POINTER; 908 pSegment->m_Image = pTRD->decode_Huffman(m_pStream.get(), grContext.get()); 909 if (!pSegment->m_Image) 910 return JBIG2_ERROR_FATAL; 911 m_pStream->alignByte(); 912 } 913 if (pSegment->m_cFlags.s.type != 4) { 914 if (!m_bBufSpecified) { 915 const auto& pPageInfo = m_PageInfoList.back(); 916 if ((pPageInfo->m_bIsStriped == 1) && 917 (ri.y + ri.height > m_pPage->height())) { 918 m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0); 919 } 920 } 921 m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Image.get(), 922 (JBig2ComposeOp)(ri.flags & 0x03)); 923 pSegment->m_Image.reset(); 924 } 925 return JBIG2_SUCCESS; 926 } 927 parsePatternDict(CJBig2_Segment * pSegment,IFX_PauseIndicator * pPause)928 int32_t CJBig2_Context::parsePatternDict(CJBig2_Segment* pSegment, 929 IFX_PauseIndicator* pPause) { 930 uint8_t cFlags; 931 auto pPDD = pdfium::MakeUnique<CJBig2_PDDProc>(); 932 if (m_pStream->read1Byte(&cFlags) != 0 || 933 m_pStream->read1Byte(&pPDD->HDPW) != 0 || 934 m_pStream->read1Byte(&pPDD->HDPH) != 0 || 935 m_pStream->readInteger(&pPDD->GRAYMAX) != 0) { 936 return JBIG2_ERROR_TOO_SHORT; 937 } 938 if (pPDD->GRAYMAX > JBIG2_MAX_PATTERN_INDEX) 939 return JBIG2_ERROR_LIMIT; 940 941 pPDD->HDMMR = cFlags & 0x01; 942 pPDD->HDTEMPLATE = (cFlags >> 1) & 0x03; 943 pSegment->m_nResultType = JBIG2_PATTERN_DICT_POINTER; 944 if (pPDD->HDMMR == 0) { 945 const size_t size = GetHuffContextSize(pPDD->HDTEMPLATE); 946 std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> gbContext( 947 FX_Alloc(JBig2ArithCtx, size)); 948 JBIG2_memset(gbContext.get(), 0, sizeof(JBig2ArithCtx) * size); 949 auto pArithDecoder = 950 pdfium::MakeUnique<CJBig2_ArithDecoder>(m_pStream.get()); 951 pSegment->m_PatternDict = 952 pPDD->decode_Arith(pArithDecoder.get(), gbContext.get(), pPause); 953 if (!pSegment->m_PatternDict) 954 return JBIG2_ERROR_FATAL; 955 956 m_pStream->alignByte(); 957 m_pStream->offset(2); 958 } else { 959 pSegment->m_PatternDict = pPDD->decode_MMR(m_pStream.get()); 960 if (!pSegment->m_PatternDict) 961 return JBIG2_ERROR_FATAL; 962 m_pStream->alignByte(); 963 } 964 return JBIG2_SUCCESS; 965 } 966 parseHalftoneRegion(CJBig2_Segment * pSegment,IFX_PauseIndicator * pPause)967 int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment, 968 IFX_PauseIndicator* pPause) { 969 uint8_t cFlags; 970 JBig2RegionInfo ri; 971 auto pHRD = pdfium::MakeUnique<CJBig2_HTRDProc>(); 972 if (parseRegionInfo(&ri) != JBIG2_SUCCESS || 973 m_pStream->read1Byte(&cFlags) != 0 || 974 m_pStream->readInteger(&pHRD->HGW) != 0 || 975 m_pStream->readInteger(&pHRD->HGH) != 0 || 976 m_pStream->readInteger((uint32_t*)&pHRD->HGX) != 0 || 977 m_pStream->readInteger((uint32_t*)&pHRD->HGY) != 0 || 978 m_pStream->readShortInteger(&pHRD->HRX) != 0 || 979 m_pStream->readShortInteger(&pHRD->HRY) != 0) { 980 return JBIG2_ERROR_TOO_SHORT; 981 } 982 983 if (pHRD->HGW == 0 || pHRD->HGH == 0) 984 return JBIG2_ERROR_FATAL; 985 986 pHRD->HBW = ri.width; 987 pHRD->HBH = ri.height; 988 pHRD->HMMR = cFlags & 0x01; 989 pHRD->HTEMPLATE = (cFlags >> 1) & 0x03; 990 pHRD->HENABLESKIP = (cFlags >> 3) & 0x01; 991 pHRD->HCOMBOP = (JBig2ComposeOp)((cFlags >> 4) & 0x07); 992 pHRD->HDEFPIXEL = (cFlags >> 7) & 0x01; 993 if (pSegment->m_nReferred_to_segment_count != 1) 994 return JBIG2_ERROR_FATAL; 995 996 CJBig2_Segment* pSeg = 997 findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[0]); 998 if (!pSeg || (pSeg->m_cFlags.s.type != 16)) 999 return JBIG2_ERROR_FATAL; 1000 1001 const CJBig2_PatternDict* pPatternDict = pSeg->m_PatternDict.get(); 1002 if (!pPatternDict || (pPatternDict->NUMPATS == 0)) 1003 return JBIG2_ERROR_FATAL; 1004 1005 pHRD->HNUMPATS = pPatternDict->NUMPATS; 1006 pHRD->HPATS = &pPatternDict->HDPATS; 1007 pHRD->HPW = pPatternDict->HDPATS[0]->width(); 1008 pHRD->HPH = pPatternDict->HDPATS[0]->height(); 1009 pSegment->m_nResultType = JBIG2_IMAGE_POINTER; 1010 if (pHRD->HMMR == 0) { 1011 const size_t size = GetHuffContextSize(pHRD->HTEMPLATE); 1012 std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> gbContext( 1013 FX_Alloc(JBig2ArithCtx, size)); 1014 JBIG2_memset(gbContext.get(), 0, sizeof(JBig2ArithCtx) * size); 1015 auto pArithDecoder = 1016 pdfium::MakeUnique<CJBig2_ArithDecoder>(m_pStream.get()); 1017 pSegment->m_Image = 1018 pHRD->decode_Arith(pArithDecoder.get(), gbContext.get(), pPause); 1019 if (!pSegment->m_Image) 1020 return JBIG2_ERROR_FATAL; 1021 1022 m_pStream->alignByte(); 1023 m_pStream->offset(2); 1024 } else { 1025 pSegment->m_Image = pHRD->decode_MMR(m_pStream.get()); 1026 if (!pSegment->m_Image) 1027 return JBIG2_ERROR_FATAL; 1028 m_pStream->alignByte(); 1029 } 1030 if (pSegment->m_cFlags.s.type != 20) { 1031 if (!m_bBufSpecified) { 1032 const auto& pPageInfo = m_PageInfoList.back(); 1033 if (pPageInfo->m_bIsStriped == 1 && 1034 ri.y + ri.height > m_pPage->height()) { 1035 m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0); 1036 } 1037 } 1038 m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Image.get(), 1039 (JBig2ComposeOp)(ri.flags & 0x03)); 1040 pSegment->m_Image.reset(); 1041 } 1042 return JBIG2_SUCCESS; 1043 } 1044 parseGenericRegion(CJBig2_Segment * pSegment,IFX_PauseIndicator * pPause)1045 int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment, 1046 IFX_PauseIndicator* pPause) { 1047 if (!m_pGRD) { 1048 auto pGRD = pdfium::MakeUnique<CJBig2_GRDProc>(); 1049 uint8_t cFlags; 1050 if (parseRegionInfo(&m_ri) != JBIG2_SUCCESS || 1051 m_pStream->read1Byte(&cFlags) != 0) { 1052 return JBIG2_ERROR_TOO_SHORT; 1053 } 1054 if (m_ri.height < 0 || m_ri.width < 0) 1055 return JBIG2_FAILED; 1056 pGRD->GBW = m_ri.width; 1057 pGRD->GBH = m_ri.height; 1058 pGRD->MMR = cFlags & 0x01; 1059 pGRD->GBTEMPLATE = (cFlags >> 1) & 0x03; 1060 pGRD->TPGDON = (cFlags >> 3) & 0x01; 1061 if (pGRD->MMR == 0) { 1062 if (pGRD->GBTEMPLATE == 0) { 1063 for (int32_t i = 0; i < 8; ++i) { 1064 if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0) 1065 return JBIG2_ERROR_TOO_SHORT; 1066 } 1067 } else { 1068 for (int32_t i = 0; i < 2; ++i) { 1069 if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0) 1070 return JBIG2_ERROR_TOO_SHORT; 1071 } 1072 } 1073 } 1074 pGRD->USESKIP = 0; 1075 m_pGRD = std::move(pGRD); 1076 } 1077 pSegment->m_nResultType = JBIG2_IMAGE_POINTER; 1078 if (m_pGRD->MMR == 0) { 1079 if (m_gbContext.empty()) 1080 m_gbContext.resize(GetHuffContextSize(m_pGRD->GBTEMPLATE)); 1081 if (!m_pArithDecoder) { 1082 m_pArithDecoder = 1083 pdfium::MakeUnique<CJBig2_ArithDecoder>(m_pStream.get()); 1084 m_ProcessingStatus = m_pGRD->Start_decode_Arith( 1085 &pSegment->m_Image, m_pArithDecoder.get(), &m_gbContext[0], pPause); 1086 } else { 1087 m_ProcessingStatus = 1088 m_pGRD->Continue_decode(pPause, m_pArithDecoder.get()); 1089 } 1090 if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) { 1091 if (pSegment->m_cFlags.s.type != 36) { 1092 if (!m_bBufSpecified) { 1093 const auto& pPageInfo = m_PageInfoList.back(); 1094 if ((pPageInfo->m_bIsStriped == 1) && 1095 (m_ri.y + m_ri.height > m_pPage->height())) { 1096 m_pPage->expand(m_ri.y + m_ri.height, 1097 (pPageInfo->m_cFlags & 4) ? 1 : 0); 1098 } 1099 } 1100 FX_RECT Rect = m_pGRD->GetReplaceRect(); 1101 m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top, 1102 pSegment->m_Image.get(), 1103 (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect); 1104 } 1105 return JBIG2_SUCCESS; 1106 } 1107 m_pArithDecoder.reset(); 1108 m_gbContext.clear(); 1109 if (!pSegment->m_Image) { 1110 m_ProcessingStatus = FXCODEC_STATUS_ERROR; 1111 m_pGRD.reset(); 1112 return JBIG2_ERROR_FATAL; 1113 } 1114 m_pStream->alignByte(); 1115 m_pStream->offset(2); 1116 } else { 1117 m_pGRD->Start_decode_MMR(&pSegment->m_Image, m_pStream.get()); 1118 if (!pSegment->m_Image) { 1119 m_pGRD.reset(); 1120 return JBIG2_ERROR_FATAL; 1121 } 1122 m_pStream->alignByte(); 1123 } 1124 if (pSegment->m_cFlags.s.type != 36) { 1125 if (!m_bBufSpecified) { 1126 JBig2PageInfo* pPageInfo = m_PageInfoList.back().get(); 1127 if ((pPageInfo->m_bIsStriped == 1) && 1128 (m_ri.y + m_ri.height > m_pPage->height())) { 1129 m_pPage->expand(m_ri.y + m_ri.height, 1130 (pPageInfo->m_cFlags & 4) ? 1 : 0); 1131 } 1132 } 1133 FX_RECT Rect = m_pGRD->GetReplaceRect(); 1134 m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top, 1135 pSegment->m_Image.get(), 1136 (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect); 1137 pSegment->m_Image.reset(); 1138 } 1139 m_pGRD.reset(); 1140 return JBIG2_SUCCESS; 1141 } 1142 parseGenericRefinementRegion(CJBig2_Segment * pSegment)1143 int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) { 1144 JBig2RegionInfo ri; 1145 uint8_t cFlags; 1146 if (parseRegionInfo(&ri) != JBIG2_SUCCESS || 1147 m_pStream->read1Byte(&cFlags) != 0) { 1148 return JBIG2_ERROR_TOO_SHORT; 1149 } 1150 auto pGRRD = pdfium::MakeUnique<CJBig2_GRRDProc>(); 1151 pGRRD->GRW = ri.width; 1152 pGRRD->GRH = ri.height; 1153 pGRRD->GRTEMPLATE = !!(cFlags & 0x01); 1154 pGRRD->TPGRON = (cFlags >> 1) & 0x01; 1155 if (!pGRRD->GRTEMPLATE) { 1156 for (int32_t i = 0; i < 4; ++i) { 1157 if (m_pStream->read1Byte((uint8_t*)&pGRRD->GRAT[i]) != 0) 1158 return JBIG2_ERROR_TOO_SHORT; 1159 } 1160 } 1161 CJBig2_Segment* pSeg = nullptr; 1162 if (pSegment->m_nReferred_to_segment_count > 0) { 1163 int32_t i; 1164 for (i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) { 1165 pSeg = findSegmentByNumber(pSegment->m_Referred_to_segment_numbers[0]); 1166 if (!pSeg) 1167 return JBIG2_ERROR_FATAL; 1168 1169 if (pSeg->m_cFlags.s.type == 4 || pSeg->m_cFlags.s.type == 20 || 1170 pSeg->m_cFlags.s.type == 36 || pSeg->m_cFlags.s.type == 40) { 1171 break; 1172 } 1173 } 1174 if (i >= pSegment->m_nReferred_to_segment_count) 1175 return JBIG2_ERROR_FATAL; 1176 1177 pGRRD->GRREFERENCE = pSeg->m_Image.get(); 1178 } else { 1179 pGRRD->GRREFERENCE = m_pPage.get(); 1180 } 1181 pGRRD->GRREFERENCEDX = 0; 1182 pGRRD->GRREFERENCEDY = 0; 1183 const size_t size = GetRefAggContextSize(pGRRD->GRTEMPLATE); 1184 std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> grContext( 1185 FX_Alloc(JBig2ArithCtx, size)); 1186 JBIG2_memset(grContext.get(), 0, sizeof(JBig2ArithCtx) * size); 1187 auto pArithDecoder = pdfium::MakeUnique<CJBig2_ArithDecoder>(m_pStream.get()); 1188 pSegment->m_nResultType = JBIG2_IMAGE_POINTER; 1189 pSegment->m_Image = pGRRD->decode(pArithDecoder.get(), grContext.get()); 1190 if (!pSegment->m_Image) 1191 return JBIG2_ERROR_FATAL; 1192 1193 m_pStream->alignByte(); 1194 m_pStream->offset(2); 1195 if (pSegment->m_cFlags.s.type != 40) { 1196 if (!m_bBufSpecified) { 1197 JBig2PageInfo* pPageInfo = m_PageInfoList.back().get(); 1198 if ((pPageInfo->m_bIsStriped == 1) && 1199 (ri.y + ri.height > m_pPage->height())) { 1200 m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0); 1201 } 1202 } 1203 m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Image.get(), 1204 (JBig2ComposeOp)(ri.flags & 0x03)); 1205 pSegment->m_Image.reset(); 1206 } 1207 return JBIG2_SUCCESS; 1208 } 1209 parseTable(CJBig2_Segment * pSegment)1210 int32_t CJBig2_Context::parseTable(CJBig2_Segment* pSegment) { 1211 pSegment->m_nResultType = JBIG2_HUFFMAN_TABLE_POINTER; 1212 pSegment->m_HuffmanTable.reset(); 1213 auto pHuff = pdfium::MakeUnique<CJBig2_HuffmanTable>(m_pStream.get()); 1214 if (!pHuff->IsOK()) 1215 return JBIG2_ERROR_FATAL; 1216 1217 pSegment->m_HuffmanTable = std::move(pHuff); 1218 m_pStream->alignByte(); 1219 return JBIG2_SUCCESS; 1220 } 1221 parseRegionInfo(JBig2RegionInfo * pRI)1222 int32_t CJBig2_Context::parseRegionInfo(JBig2RegionInfo* pRI) { 1223 if (m_pStream->readInteger((uint32_t*)&pRI->width) != 0 || 1224 m_pStream->readInteger((uint32_t*)&pRI->height) != 0 || 1225 m_pStream->readInteger((uint32_t*)&pRI->x) != 0 || 1226 m_pStream->readInteger((uint32_t*)&pRI->y) != 0 || 1227 m_pStream->read1Byte(&pRI->flags) != 0) { 1228 return JBIG2_ERROR_TOO_SHORT; 1229 } 1230 return JBIG2_SUCCESS; 1231 } 1232 decodeSymbolIDHuffmanTable(CJBig2_BitStream * pStream,uint32_t SBNUMSYMS)1233 std::vector<JBig2HuffmanCode> CJBig2_Context::decodeSymbolIDHuffmanTable( 1234 CJBig2_BitStream* pStream, 1235 uint32_t SBNUMSYMS) { 1236 const size_t kRunCodesSize = 35; 1237 JBig2HuffmanCode huffman_codes[kRunCodesSize]; 1238 for (size_t i = 0; i < kRunCodesSize; ++i) { 1239 if (pStream->readNBits(4, &huffman_codes[i].codelen) != 0) 1240 return std::vector<JBig2HuffmanCode>(); 1241 } 1242 huffman_assign_code(huffman_codes, kRunCodesSize); 1243 1244 std::vector<JBig2HuffmanCode> SBSYMCODES(SBNUMSYMS); 1245 int32_t run = 0; 1246 int32_t i = 0; 1247 while (i < static_cast<int>(SBNUMSYMS)) { 1248 size_t j; 1249 int32_t nVal = 0; 1250 int32_t nBits = 0; 1251 uint32_t nTemp; 1252 while (true) { 1253 if (nVal > std::numeric_limits<int32_t>::max() / 2 || 1254 pStream->read1Bit(&nTemp) != 0) { 1255 return std::vector<JBig2HuffmanCode>(); 1256 } 1257 1258 nVal = (nVal << 1) | nTemp; 1259 ++nBits; 1260 for (j = 0; j < kRunCodesSize; ++j) { 1261 if (nBits == huffman_codes[j].codelen && nVal == huffman_codes[j].code) 1262 break; 1263 } 1264 if (j < kRunCodesSize) 1265 break; 1266 } 1267 int32_t runcode = static_cast<int32_t>(j); 1268 if (runcode < 32) { 1269 SBSYMCODES[i].codelen = runcode; 1270 run = 0; 1271 } else if (runcode == 32) { 1272 if (pStream->readNBits(2, &nTemp) != 0) 1273 return std::vector<JBig2HuffmanCode>(); 1274 run = nTemp + 3; 1275 } else if (runcode == 33) { 1276 if (pStream->readNBits(3, &nTemp) != 0) 1277 return std::vector<JBig2HuffmanCode>(); 1278 run = nTemp + 3; 1279 } else if (runcode == 34) { 1280 if (pStream->readNBits(7, &nTemp) != 0) 1281 return std::vector<JBig2HuffmanCode>(); 1282 run = nTemp + 11; 1283 } 1284 if (run > 0) { 1285 if (i + run > (int)SBNUMSYMS) 1286 return std::vector<JBig2HuffmanCode>(); 1287 for (int32_t k = 0; k < run; ++k) { 1288 if (runcode == 32 && i > 0) 1289 SBSYMCODES[i + k].codelen = SBSYMCODES[i - 1].codelen; 1290 else 1291 SBSYMCODES[i + k].codelen = 0; 1292 } 1293 i += run; 1294 } else { 1295 ++i; 1296 } 1297 } 1298 huffman_assign_code(SBSYMCODES.data(), SBNUMSYMS); 1299 return SBSYMCODES; 1300 } 1301 huffman_assign_code(JBig2HuffmanCode * SBSYMCODES,int NTEMP)1302 void CJBig2_Context::huffman_assign_code(JBig2HuffmanCode* SBSYMCODES, 1303 int NTEMP) { 1304 // TODO(thestig) CJBig2_HuffmanTable::parseFromCodedBuffer() has similar code. 1305 int LENMAX = 0; 1306 for (int i = 0; i < NTEMP; ++i) 1307 LENMAX = std::max(LENMAX, SBSYMCODES[i].codelen); 1308 std::vector<int> LENCOUNT(LENMAX + 1); 1309 std::vector<int> FIRSTCODE(LENMAX + 1); 1310 for (int i = 0; i < NTEMP; ++i) 1311 ++LENCOUNT[SBSYMCODES[i].codelen]; 1312 LENCOUNT[0] = 0; 1313 for (int CURLEN = 1; CURLEN <= LENMAX; ++CURLEN) { 1314 FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1; 1315 int CURCODE = FIRSTCODE[CURLEN]; 1316 for (int CURTEMP = 0; CURTEMP < NTEMP; ++CURTEMP) { 1317 if (SBSYMCODES[CURTEMP].codelen == CURLEN) { 1318 SBSYMCODES[CURTEMP].code = CURCODE; 1319 CURCODE = CURCODE + 1; 1320 } 1321 } 1322 } 1323 } 1324