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