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