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