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
GetHuffContextSize(uint8_t val)30 size_t GetHuffContextSize(uint8_t val) {
31 return val == 0 ? 65536 : val == 1 ? 8192 : 1024;
32 }
33
GetRefAggContextSize(bool val)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
CJBig2_Context(CPDF_StreamAcc * pGlobalStream,CPDF_StreamAcc * pSrcStream,std::list<CJBig2_CachePair> * pSymbolDictCache,IFX_Pause * pPause,bool bIsGlobal)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
~CJBig2_Context()70 CJBig2_Context::~CJBig2_Context() {}
71
decode_SquentialOrgnazation(IFX_Pause * pPause)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
decode_EmbedOrgnazation(IFX_Pause * pPause)118 int32_t CJBig2_Context::decode_EmbedOrgnazation(IFX_Pause* pPause) {
119 return decode_SquentialOrgnazation(pPause);
120 }
121
decode_RandomOrgnazation_FirstPage(IFX_Pause * pPause)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
decode_RandomOrgnazation(IFX_Pause * pPause)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
getFirstPage(uint8_t * pBuf,int32_t width,int32_t height,int32_t stride,IFX_Pause * pPause)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
Continue(IFX_Pause * pPause)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
findSegmentByNumber(uint32_t dwNumber)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
findReferredSegmentByTypeAndIndex(CJBig2_Segment * pSegment,uint8_t cType,int32_t nIndex)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
parseSegmentHeader(CJBig2_Segment * pSegment)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
parseSegmentData(CJBig2_Segment * pSegment,IFX_Pause * pPause)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
ProcessingParseSegmentData(CJBig2_Segment * pSegment,IFX_Pause * pPause)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
parseSymbolDict(CJBig2_Segment * pSegment,IFX_Pause * pPause)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
parseTextRegion(CJBig2_Segment * pSegment)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
parsePatternDict(CJBig2_Segment * pSegment,IFX_Pause * pPause)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
parseHalftoneRegion(CJBig2_Segment * pSegment,IFX_Pause * pPause)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
parseGenericRegion(CJBig2_Segment * pSegment,IFX_Pause * pPause)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
parseGenericRefinementRegion(CJBig2_Segment * pSegment)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
parseTable(CJBig2_Segment * pSegment)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
parseRegionInfo(JBig2RegionInfo * pRI)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
decodeSymbolIDHuffmanTable(CJBig2_BitStream * pStream,uint32_t SBNUMSYMS)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
huffman_assign_code(int * CODES,int * PREFLEN,int NTEMP)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
huffman_assign_code(JBig2HuffmanCode * SBSYMCODES,int NTEMP)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