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(std::make_unique<CJBig2_BitStream>(pSrcSpan, dwObjNum)),
74 m_HuffmanTables(CJBig2_HuffmanTable::kNumHuffmanTables),
75 m_bIsGlobal(bIsGlobal),
76 m_pSymbolDictCache(pSymbolDictCache) {}
77
78 CJBig2_Context::~CJBig2_Context() = default;
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 = std::make_unique<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 = std::make_unique<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 = std::make_unique<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 = std::make_unique<CJBig2_Image>(pPageInfo->m_dwWidth, height);
341 }
342
343 if (!m_pPage->data()) {
344 m_ProcessingStatus = FXCODEC_STATUS_ERROR;
345 return JBig2_Result::kFailure;
346 }
347
348 m_pPage->Fill((pPageInfo->m_cFlags & 4) ? 1 : 0);
349 m_PageInfoList.push_back(std::move(pPageInfo));
350 m_bInPage = true;
351 } break;
352 case 49:
353 m_bInPage = false;
354 return JBig2_Result::kEndReached;
355 break;
356 case 50:
357 m_pStream->offset(pSegment->m_dwData_length);
358 break;
359 case 51:
360 return JBig2_Result::kEndReached;
361 case 52:
362 m_pStream->offset(pSegment->m_dwData_length);
363 break;
364 case 53:
365 return ParseTable(pSegment);
366 case 62:
367 m_pStream->offset(pSegment->m_dwData_length);
368 break;
369 default:
370 break;
371 }
372 return JBig2_Result::kSuccess;
373 }
374
ParseSymbolDict(CJBig2_Segment * pSegment)375 JBig2_Result CJBig2_Context::ParseSymbolDict(CJBig2_Segment* pSegment) {
376 uint16_t wFlags;
377 if (m_pStream->readShortInteger(&wFlags) != 0)
378 return JBig2_Result::kFailure;
379
380 auto pSymbolDictDecoder = std::make_unique<CJBig2_SDDProc>();
381 pSymbolDictDecoder->SDHUFF = wFlags & 0x0001;
382 pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001;
383 pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003;
384 pSymbolDictDecoder->SDRTEMPLATE = !!((wFlags >> 12) & 0x0003);
385 if (pSymbolDictDecoder->SDHUFF == 0) {
386 const uint32_t dwTemp = (pSymbolDictDecoder->SDTEMPLATE == 0) ? 8 : 2;
387 for (uint32_t i = 0; i < dwTemp; ++i) {
388 if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDAT[i]) != 0)
389 return JBig2_Result::kFailure;
390 }
391 }
392 if (pSymbolDictDecoder->SDREFAGG == 1 && !pSymbolDictDecoder->SDRTEMPLATE) {
393 for (int32_t i = 0; i < 4; ++i) {
394 if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDRAT[i]) != 0)
395 return JBig2_Result::kFailure;
396 }
397 }
398 if (m_pStream->readInteger(&pSymbolDictDecoder->SDNUMEXSYMS) != 0 ||
399 m_pStream->readInteger(&pSymbolDictDecoder->SDNUMNEWSYMS) != 0) {
400 return JBig2_Result::kFailure;
401 }
402 if (pSymbolDictDecoder->SDNUMEXSYMS > JBIG2_MAX_EXPORT_SYSMBOLS ||
403 pSymbolDictDecoder->SDNUMNEWSYMS > JBIG2_MAX_NEW_SYSMBOLS) {
404 return JBig2_Result::kFailure;
405 }
406 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
407 if (!FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]))
408 return JBig2_Result::kFailure;
409 }
410 CJBig2_Segment* pLRSeg = nullptr;
411 pSymbolDictDecoder->SDNUMINSYMS = 0;
412 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
413 CJBig2_Segment* pSeg =
414 FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]);
415 if (pSeg->m_cFlags.s.type == 0) {
416 pSymbolDictDecoder->SDNUMINSYMS += pSeg->m_SymbolDict->NumImages();
417 pLRSeg = pSeg;
418 }
419 }
420
421 std::unique_ptr<CJBig2_Image*, FxFreeDeleter> SDINSYMS;
422 if (pSymbolDictDecoder->SDNUMINSYMS != 0) {
423 SDINSYMS.reset(FX_Alloc(CJBig2_Image*, pSymbolDictDecoder->SDNUMINSYMS));
424 uint32_t dwTemp = 0;
425 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
426 CJBig2_Segment* pSeg =
427 FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]);
428 if (pSeg->m_cFlags.s.type == 0) {
429 const CJBig2_SymbolDict& dict = *pSeg->m_SymbolDict;
430 for (size_t j = 0; j < dict.NumImages(); ++j)
431 SDINSYMS.get()[dwTemp + j] = dict.GetImage(j);
432 dwTemp += dict.NumImages();
433 }
434 }
435 }
436 pSymbolDictDecoder->SDINSYMS = SDINSYMS.get();
437
438 uint8_t cSDHUFFDH = (wFlags >> 2) & 0x0003;
439 uint8_t cSDHUFFDW = (wFlags >> 4) & 0x0003;
440 if (pSymbolDictDecoder->SDHUFF == 1) {
441 if (cSDHUFFDH == 2 || cSDHUFFDW == 2)
442 return JBig2_Result::kFailure;
443
444 int32_t nIndex = 0;
445 if (cSDHUFFDH == 0) {
446 pSymbolDictDecoder->SDHUFFDH = GetHuffmanTable(4);
447 } else if (cSDHUFFDH == 1) {
448 pSymbolDictDecoder->SDHUFFDH = GetHuffmanTable(5);
449 } else {
450 CJBig2_Segment* pSeg =
451 FindReferredTableSegmentByIndex(pSegment, nIndex++);
452 if (!pSeg)
453 return JBig2_Result::kFailure;
454 pSymbolDictDecoder->SDHUFFDH = pSeg->m_HuffmanTable.get();
455 }
456 if (cSDHUFFDW == 0) {
457 pSymbolDictDecoder->SDHUFFDW = GetHuffmanTable(2);
458 } else if (cSDHUFFDW == 1) {
459 pSymbolDictDecoder->SDHUFFDW = GetHuffmanTable(3);
460 } else {
461 CJBig2_Segment* pSeg =
462 FindReferredTableSegmentByIndex(pSegment, nIndex++);
463 if (!pSeg)
464 return JBig2_Result::kFailure;
465 pSymbolDictDecoder->SDHUFFDW = pSeg->m_HuffmanTable.get();
466 }
467 uint8_t cSDHUFFBMSIZE = (wFlags >> 6) & 0x0001;
468 if (cSDHUFFBMSIZE == 0) {
469 pSymbolDictDecoder->SDHUFFBMSIZE = GetHuffmanTable(1);
470 } else {
471 CJBig2_Segment* pSeg =
472 FindReferredTableSegmentByIndex(pSegment, nIndex++);
473 if (!pSeg)
474 return JBig2_Result::kFailure;
475 pSymbolDictDecoder->SDHUFFBMSIZE = pSeg->m_HuffmanTable.get();
476 }
477 if (pSymbolDictDecoder->SDREFAGG == 1) {
478 uint8_t cSDHUFFAGGINST = (wFlags >> 7) & 0x0001;
479 if (cSDHUFFAGGINST == 0) {
480 pSymbolDictDecoder->SDHUFFAGGINST = GetHuffmanTable(1);
481 } else {
482 CJBig2_Segment* pSeg =
483 FindReferredTableSegmentByIndex(pSegment, nIndex++);
484 if (!pSeg)
485 return JBig2_Result::kFailure;
486 pSymbolDictDecoder->SDHUFFAGGINST = pSeg->m_HuffmanTable.get();
487 }
488 }
489 }
490
491 const bool bUseGbContext = (pSymbolDictDecoder->SDHUFF == 0);
492 const bool bUseGrContext = (pSymbolDictDecoder->SDREFAGG == 1);
493 const size_t gbContextSize =
494 GetHuffContextSize(pSymbolDictDecoder->SDTEMPLATE);
495 const size_t grContextSize =
496 GetRefAggContextSize(pSymbolDictDecoder->SDRTEMPLATE);
497 std::vector<JBig2ArithCtx> gbContext;
498 std::vector<JBig2ArithCtx> grContext;
499 if ((wFlags & 0x0100) && pLRSeg) {
500 if (bUseGbContext) {
501 gbContext = pLRSeg->m_SymbolDict->GbContext();
502 if (gbContext.size() != gbContextSize)
503 return JBig2_Result::kFailure;
504 }
505 if (bUseGrContext) {
506 grContext = pLRSeg->m_SymbolDict->GrContext();
507 if (grContext.size() != grContextSize)
508 return JBig2_Result::kFailure;
509 }
510 } else {
511 if (bUseGbContext)
512 gbContext.resize(gbContextSize);
513 if (bUseGrContext)
514 grContext.resize(grContextSize);
515 }
516
517 CJBig2_CacheKey key =
518 CJBig2_CacheKey(pSegment->m_dwObjNum, pSegment->m_dwDataOffset);
519 bool cache_hit = false;
520 pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER;
521 if (m_bIsGlobal && key.first != 0) {
522 for (auto it = m_pSymbolDictCache->begin(); it != m_pSymbolDictCache->end();
523 ++it) {
524 if (it->first == key) {
525 pSegment->m_SymbolDict = it->second->DeepCopy();
526 m_pSymbolDictCache->push_front(
527 CJBig2_CachePair(key, std::move(it->second)));
528 m_pSymbolDictCache->erase(it);
529 cache_hit = true;
530 break;
531 }
532 }
533 }
534 if (!cache_hit) {
535 if (bUseGbContext) {
536 auto pArithDecoder =
537 std::make_unique<CJBig2_ArithDecoder>(m_pStream.get());
538 pSegment->m_SymbolDict = pSymbolDictDecoder->DecodeArith(
539 pArithDecoder.get(), &gbContext, &grContext);
540 if (!pSegment->m_SymbolDict)
541 return JBig2_Result::kFailure;
542
543 m_pStream->alignByte();
544 m_pStream->offset(2);
545 } else {
546 pSegment->m_SymbolDict = pSymbolDictDecoder->DecodeHuffman(
547 m_pStream.get(), &gbContext, &grContext);
548 if (!pSegment->m_SymbolDict)
549 return JBig2_Result::kFailure;
550 m_pStream->alignByte();
551 }
552 if (m_bIsGlobal) {
553 std::unique_ptr<CJBig2_SymbolDict> value =
554 pSegment->m_SymbolDict->DeepCopy();
555 size_t size = m_pSymbolDictCache->size();
556 while (size >= kSymbolDictCacheMaxSize) {
557 m_pSymbolDictCache->pop_back();
558 --size;
559 }
560 m_pSymbolDictCache->push_front(CJBig2_CachePair(key, std::move(value)));
561 }
562 }
563 if (wFlags & 0x0200) {
564 if (bUseGbContext)
565 pSegment->m_SymbolDict->SetGbContext(std::move(gbContext));
566 if (bUseGrContext)
567 pSegment->m_SymbolDict->SetGrContext(std::move(grContext));
568 }
569 return JBig2_Result::kSuccess;
570 }
571
ParseTextRegion(CJBig2_Segment * pSegment)572 JBig2_Result CJBig2_Context::ParseTextRegion(CJBig2_Segment* pSegment) {
573 uint16_t wFlags;
574 JBig2RegionInfo ri;
575 if (ParseRegionInfo(&ri) != JBig2_Result::kSuccess ||
576 m_pStream->readShortInteger(&wFlags) != 0) {
577 return JBig2_Result::kFailure;
578 }
579 if (!CJBig2_Image::IsValidImageSize(ri.width, ri.height))
580 return JBig2_Result::kFailure;
581
582 auto pTRD = std::make_unique<CJBig2_TRDProc>();
583 pTRD->SBW = ri.width;
584 pTRD->SBH = ri.height;
585 pTRD->SBHUFF = wFlags & 0x0001;
586 pTRD->SBREFINE = (wFlags >> 1) & 0x0001;
587 uint32_t dwTemp = (wFlags >> 2) & 0x0003;
588 pTRD->SBSTRIPS = 1 << dwTemp;
589 pTRD->REFCORNER = (JBig2Corner)((wFlags >> 4) & 0x0003);
590 pTRD->TRANSPOSED = (wFlags >> 6) & 0x0001;
591 pTRD->SBCOMBOP = (JBig2ComposeOp)((wFlags >> 7) & 0x0003);
592 pTRD->SBDEFPIXEL = (wFlags >> 9) & 0x0001;
593 pTRD->SBDSOFFSET = (wFlags >> 10) & 0x001f;
594 if (pTRD->SBDSOFFSET >= 0x0010) {
595 pTRD->SBDSOFFSET = pTRD->SBDSOFFSET - 0x0020;
596 }
597 pTRD->SBRTEMPLATE = !!((wFlags >> 15) & 0x0001);
598
599 if (pTRD->SBHUFF == 1 && m_pStream->readShortInteger(&wFlags) != 0) {
600 return JBig2_Result::kFailure;
601 }
602 if (pTRD->SBREFINE == 1 && !pTRD->SBRTEMPLATE) {
603 for (int32_t i = 0; i < 4; ++i) {
604 if (m_pStream->read1Byte((uint8_t*)&pTRD->SBRAT[i]) != 0)
605 return JBig2_Result::kFailure;
606 }
607 }
608 if (m_pStream->readInteger(&pTRD->SBNUMINSTANCES) != 0)
609 return JBig2_Result::kFailure;
610
611 // Assume each instance takes at least 0.25 bits when encoded. That means for
612 // a stream of length N bytes, there can be at most 32N instances. This is a
613 // conservative estimate just to sanitize the |SBNUMINSTANCES| value.
614 // Use FX_SAFE_INT32 to be safe, though it should never overflow because PDFs
615 // have a maximum size of roughly 11 GB.
616 FX_SAFE_INT32 nMaxStripInstances = m_pStream->getLength();
617 nMaxStripInstances *= 32;
618 if (pTRD->SBNUMINSTANCES > nMaxStripInstances.ValueOrDie())
619 return JBig2_Result::kFailure;
620
621 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
622 if (!FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]))
623 return JBig2_Result::kFailure;
624 }
625
626 pTRD->SBNUMSYMS = 0;
627 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
628 CJBig2_Segment* pSeg =
629 FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]);
630 if (pSeg->m_cFlags.s.type == 0) {
631 pTRD->SBNUMSYMS += pSeg->m_SymbolDict->NumImages();
632 }
633 }
634
635 std::unique_ptr<CJBig2_Image*, FxFreeDeleter> SBSYMS;
636 if (pTRD->SBNUMSYMS > 0) {
637 SBSYMS.reset(FX_Alloc(CJBig2_Image*, pTRD->SBNUMSYMS));
638 dwTemp = 0;
639 for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
640 CJBig2_Segment* pSeg =
641 FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[i]);
642 if (pSeg->m_cFlags.s.type == 0) {
643 const CJBig2_SymbolDict& dict = *pSeg->m_SymbolDict;
644 for (size_t j = 0; j < dict.NumImages(); ++j)
645 SBSYMS.get()[dwTemp + j] = dict.GetImage(j);
646 dwTemp += dict.NumImages();
647 }
648 }
649 pTRD->SBSYMS = SBSYMS.get();
650 } else {
651 pTRD->SBSYMS = nullptr;
652 }
653
654 if (pTRD->SBHUFF == 1) {
655 std::vector<JBig2HuffmanCode> SBSYMCODES =
656 DecodeSymbolIDHuffmanTable(pTRD->SBNUMSYMS);
657 if (SBSYMCODES.empty())
658 return JBig2_Result::kFailure;
659
660 m_pStream->alignByte();
661 pTRD->SBSYMCODES = std::move(SBSYMCODES);
662 } else {
663 dwTemp = 0;
664 while ((uint32_t)(1 << dwTemp) < pTRD->SBNUMSYMS) {
665 ++dwTemp;
666 }
667 pTRD->SBSYMCODELEN = (uint8_t)dwTemp;
668 }
669
670 if (pTRD->SBHUFF == 1) {
671 uint8_t cSBHUFFFS = wFlags & 0x0003;
672 uint8_t cSBHUFFDS = (wFlags >> 2) & 0x0003;
673 uint8_t cSBHUFFDT = (wFlags >> 4) & 0x0003;
674 uint8_t cSBHUFFRDW = (wFlags >> 6) & 0x0003;
675 uint8_t cSBHUFFRDH = (wFlags >> 8) & 0x0003;
676 uint8_t cSBHUFFRDX = (wFlags >> 10) & 0x0003;
677 uint8_t cSBHUFFRDY = (wFlags >> 12) & 0x0003;
678 uint8_t cSBHUFFRSIZE = (wFlags >> 14) & 0x0001;
679 if (cSBHUFFFS == 2 || cSBHUFFRDW == 2 || cSBHUFFRDH == 2 ||
680 cSBHUFFRDX == 2 || cSBHUFFRDY == 2) {
681 return JBig2_Result::kFailure;
682 }
683 int32_t nIndex = 0;
684 if (cSBHUFFFS == 0) {
685 pTRD->SBHUFFFS = GetHuffmanTable(6);
686 } else if (cSBHUFFFS == 1) {
687 pTRD->SBHUFFFS = GetHuffmanTable(7);
688 } else {
689 CJBig2_Segment* pSeg =
690 FindReferredTableSegmentByIndex(pSegment, nIndex++);
691 if (!pSeg)
692 return JBig2_Result::kFailure;
693 pTRD->SBHUFFFS = pSeg->m_HuffmanTable.get();
694 }
695 if (cSBHUFFDS == 0) {
696 pTRD->SBHUFFDS = GetHuffmanTable(8);
697 } else if (cSBHUFFDS == 1) {
698 pTRD->SBHUFFDS = GetHuffmanTable(9);
699 } else if (cSBHUFFDS == 2) {
700 pTRD->SBHUFFDS = GetHuffmanTable(10);
701 } else {
702 CJBig2_Segment* pSeg =
703 FindReferredTableSegmentByIndex(pSegment, nIndex++);
704 if (!pSeg)
705 return JBig2_Result::kFailure;
706 pTRD->SBHUFFDS = pSeg->m_HuffmanTable.get();
707 }
708 if (cSBHUFFDT == 0) {
709 pTRD->SBHUFFDT = GetHuffmanTable(11);
710 } else if (cSBHUFFDT == 1) {
711 pTRD->SBHUFFDT = GetHuffmanTable(12);
712 } else if (cSBHUFFDT == 2) {
713 pTRD->SBHUFFDT = GetHuffmanTable(13);
714 } else {
715 CJBig2_Segment* pSeg =
716 FindReferredTableSegmentByIndex(pSegment, nIndex++);
717 if (!pSeg)
718 return JBig2_Result::kFailure;
719 pTRD->SBHUFFDT = pSeg->m_HuffmanTable.get();
720 }
721 if (cSBHUFFRDW == 0) {
722 pTRD->SBHUFFRDW = GetHuffmanTable(14);
723 } else if (cSBHUFFRDW == 1) {
724 pTRD->SBHUFFRDW = GetHuffmanTable(15);
725 } else {
726 CJBig2_Segment* pSeg =
727 FindReferredTableSegmentByIndex(pSegment, nIndex++);
728 if (!pSeg)
729 return JBig2_Result::kFailure;
730 pTRD->SBHUFFRDW = pSeg->m_HuffmanTable.get();
731 }
732 if (cSBHUFFRDH == 0) {
733 pTRD->SBHUFFRDH = GetHuffmanTable(14);
734 } else if (cSBHUFFRDH == 1) {
735 pTRD->SBHUFFRDH = GetHuffmanTable(15);
736 } else {
737 CJBig2_Segment* pSeg =
738 FindReferredTableSegmentByIndex(pSegment, nIndex++);
739 if (!pSeg)
740 return JBig2_Result::kFailure;
741 pTRD->SBHUFFRDH = pSeg->m_HuffmanTable.get();
742 }
743 if (cSBHUFFRDX == 0) {
744 pTRD->SBHUFFRDX = GetHuffmanTable(14);
745 } else if (cSBHUFFRDX == 1) {
746 pTRD->SBHUFFRDX = GetHuffmanTable(15);
747 } else {
748 CJBig2_Segment* pSeg =
749 FindReferredTableSegmentByIndex(pSegment, nIndex++);
750 if (!pSeg)
751 return JBig2_Result::kFailure;
752 pTRD->SBHUFFRDX = pSeg->m_HuffmanTable.get();
753 }
754 if (cSBHUFFRDY == 0) {
755 pTRD->SBHUFFRDY = GetHuffmanTable(14);
756 } else if (cSBHUFFRDY == 1) {
757 pTRD->SBHUFFRDY = GetHuffmanTable(15);
758 } else {
759 CJBig2_Segment* pSeg =
760 FindReferredTableSegmentByIndex(pSegment, nIndex++);
761 if (!pSeg)
762 return JBig2_Result::kFailure;
763 pTRD->SBHUFFRDY = pSeg->m_HuffmanTable.get();
764 }
765 if (cSBHUFFRSIZE == 0) {
766 pTRD->SBHUFFRSIZE = GetHuffmanTable(1);
767 } else {
768 CJBig2_Segment* pSeg =
769 FindReferredTableSegmentByIndex(pSegment, nIndex++);
770 if (!pSeg)
771 return JBig2_Result::kFailure;
772 pTRD->SBHUFFRSIZE = pSeg->m_HuffmanTable.get();
773 }
774 }
775 std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> grContext;
776 if (pTRD->SBREFINE == 1) {
777 const size_t size = GetRefAggContextSize(pTRD->SBRTEMPLATE);
778 grContext.reset(FX_Alloc(JBig2ArithCtx, size));
779 }
780 if (pTRD->SBHUFF == 0) {
781 auto pArithDecoder = std::make_unique<CJBig2_ArithDecoder>(m_pStream.get());
782 pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
783 pSegment->m_Image =
784 pTRD->DecodeArith(pArithDecoder.get(), grContext.get(), nullptr);
785 if (!pSegment->m_Image)
786 return JBig2_Result::kFailure;
787 m_pStream->alignByte();
788 m_pStream->offset(2);
789 } else {
790 pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
791 pSegment->m_Image = pTRD->DecodeHuffman(m_pStream.get(), grContext.get());
792 if (!pSegment->m_Image)
793 return JBig2_Result::kFailure;
794 m_pStream->alignByte();
795 }
796 if (pSegment->m_cFlags.s.type != 4) {
797 if (!m_bBufSpecified) {
798 const auto& pPageInfo = m_PageInfoList.back();
799 if ((pPageInfo->m_bIsStriped == 1) &&
800 (ri.y + ri.height > m_pPage->height())) {
801 m_pPage->Expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
802 }
803 }
804 m_pPage->ComposeFrom(ri.x, ri.y, pSegment->m_Image.get(),
805 (JBig2ComposeOp)(ri.flags & 0x03));
806 pSegment->m_Image.reset();
807 }
808 return JBig2_Result::kSuccess;
809 }
810
ParsePatternDict(CJBig2_Segment * pSegment,PauseIndicatorIface * pPause)811 JBig2_Result CJBig2_Context::ParsePatternDict(CJBig2_Segment* pSegment,
812 PauseIndicatorIface* pPause) {
813 uint8_t cFlags;
814 auto pPDD = std::make_unique<CJBig2_PDDProc>();
815 if (m_pStream->read1Byte(&cFlags) != 0 ||
816 m_pStream->read1Byte(&pPDD->HDPW) != 0 ||
817 m_pStream->read1Byte(&pPDD->HDPH) != 0 ||
818 m_pStream->readInteger(&pPDD->GRAYMAX) != 0) {
819 return JBig2_Result::kFailure;
820 }
821 if (pPDD->GRAYMAX > JBIG2_MAX_PATTERN_INDEX)
822 return JBig2_Result::kFailure;
823
824 pPDD->HDMMR = cFlags & 0x01;
825 pPDD->HDTEMPLATE = (cFlags >> 1) & 0x03;
826 pSegment->m_nResultType = JBIG2_PATTERN_DICT_POINTER;
827 if (pPDD->HDMMR == 0) {
828 const size_t size = GetHuffContextSize(pPDD->HDTEMPLATE);
829 std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> gbContext(
830 FX_Alloc(JBig2ArithCtx, size));
831 auto pArithDecoder = std::make_unique<CJBig2_ArithDecoder>(m_pStream.get());
832 pSegment->m_PatternDict =
833 pPDD->DecodeArith(pArithDecoder.get(), gbContext.get(), pPause);
834 if (!pSegment->m_PatternDict)
835 return JBig2_Result::kFailure;
836
837 m_pStream->alignByte();
838 m_pStream->offset(2);
839 } else {
840 pSegment->m_PatternDict = pPDD->DecodeMMR(m_pStream.get());
841 if (!pSegment->m_PatternDict)
842 return JBig2_Result::kFailure;
843 m_pStream->alignByte();
844 }
845 return JBig2_Result::kSuccess;
846 }
847
ParseHalftoneRegion(CJBig2_Segment * pSegment,PauseIndicatorIface * pPause)848 JBig2_Result CJBig2_Context::ParseHalftoneRegion(CJBig2_Segment* pSegment,
849 PauseIndicatorIface* pPause) {
850 uint8_t cFlags;
851 JBig2RegionInfo ri;
852 auto pHRD = std::make_unique<CJBig2_HTRDProc>();
853 if (ParseRegionInfo(&ri) != JBig2_Result::kSuccess ||
854 m_pStream->read1Byte(&cFlags) != 0 ||
855 m_pStream->readInteger(&pHRD->HGW) != 0 ||
856 m_pStream->readInteger(&pHRD->HGH) != 0 ||
857 m_pStream->readInteger((uint32_t*)&pHRD->HGX) != 0 ||
858 m_pStream->readInteger((uint32_t*)&pHRD->HGY) != 0 ||
859 m_pStream->readShortInteger(&pHRD->HRX) != 0 ||
860 m_pStream->readShortInteger(&pHRD->HRY) != 0) {
861 return JBig2_Result::kFailure;
862 }
863
864 if (!CJBig2_Image::IsValidImageSize(pHRD->HGW, pHRD->HGH))
865 return JBig2_Result::kFailure;
866
867 if (!CJBig2_Image::IsValidImageSize(ri.width, ri.height))
868 return JBig2_Result::kFailure;
869
870 pHRD->HBW = ri.width;
871 pHRD->HBH = ri.height;
872 pHRD->HMMR = cFlags & 0x01;
873 pHRD->HTEMPLATE = (cFlags >> 1) & 0x03;
874 pHRD->HENABLESKIP = (cFlags >> 3) & 0x01;
875 pHRD->HCOMBOP = (JBig2ComposeOp)((cFlags >> 4) & 0x07);
876 pHRD->HDEFPIXEL = (cFlags >> 7) & 0x01;
877 if (pSegment->m_nReferred_to_segment_count != 1)
878 return JBig2_Result::kFailure;
879
880 CJBig2_Segment* pSeg =
881 FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[0]);
882 if (!pSeg || (pSeg->m_cFlags.s.type != 16))
883 return JBig2_Result::kFailure;
884
885 const CJBig2_PatternDict* pPatternDict = pSeg->m_PatternDict.get();
886 if (!pPatternDict || (pPatternDict->NUMPATS == 0))
887 return JBig2_Result::kFailure;
888
889 pHRD->HNUMPATS = pPatternDict->NUMPATS;
890 pHRD->HPATS = &pPatternDict->HDPATS;
891 pHRD->HPW = pPatternDict->HDPATS[0]->width();
892 pHRD->HPH = pPatternDict->HDPATS[0]->height();
893 pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
894 if (pHRD->HMMR == 0) {
895 const size_t size = GetHuffContextSize(pHRD->HTEMPLATE);
896 std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> gbContext(
897 FX_Alloc(JBig2ArithCtx, size));
898 auto pArithDecoder = std::make_unique<CJBig2_ArithDecoder>(m_pStream.get());
899 pSegment->m_Image =
900 pHRD->DecodeArith(pArithDecoder.get(), gbContext.get(), pPause);
901 if (!pSegment->m_Image)
902 return JBig2_Result::kFailure;
903
904 m_pStream->alignByte();
905 m_pStream->offset(2);
906 } else {
907 pSegment->m_Image = pHRD->DecodeMMR(m_pStream.get());
908 if (!pSegment->m_Image)
909 return JBig2_Result::kFailure;
910 m_pStream->alignByte();
911 }
912 if (pSegment->m_cFlags.s.type != 20) {
913 if (!m_bBufSpecified) {
914 const auto& pPageInfo = m_PageInfoList.back();
915 if (pPageInfo->m_bIsStriped == 1 &&
916 ri.y + ri.height > m_pPage->height()) {
917 m_pPage->Expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
918 }
919 }
920 m_pPage->ComposeFrom(ri.x, ri.y, pSegment->m_Image.get(),
921 (JBig2ComposeOp)(ri.flags & 0x03));
922 pSegment->m_Image.reset();
923 }
924 return JBig2_Result::kSuccess;
925 }
926
ParseGenericRegion(CJBig2_Segment * pSegment,PauseIndicatorIface * pPause)927 JBig2_Result CJBig2_Context::ParseGenericRegion(CJBig2_Segment* pSegment,
928 PauseIndicatorIface* pPause) {
929 if (!m_pGRD) {
930 auto pGRD = std::make_unique<CJBig2_GRDProc>();
931 uint8_t cFlags;
932 if (ParseRegionInfo(&m_ri) != JBig2_Result::kSuccess ||
933 m_pStream->read1Byte(&cFlags) != 0) {
934 return JBig2_Result::kFailure;
935 }
936 if (m_ri.height < 0 || m_ri.width < 0)
937 return JBig2_Result::kFailure;
938 pGRD->GBW = m_ri.width;
939 pGRD->GBH = m_ri.height;
940 pGRD->MMR = cFlags & 0x01;
941 pGRD->GBTEMPLATE = (cFlags >> 1) & 0x03;
942 pGRD->TPGDON = (cFlags >> 3) & 0x01;
943 if (pGRD->MMR == 0) {
944 if (pGRD->GBTEMPLATE == 0) {
945 for (int32_t i = 0; i < 8; ++i) {
946 if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0)
947 return JBig2_Result::kFailure;
948 }
949 } else {
950 for (int32_t i = 0; i < 2; ++i) {
951 if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0)
952 return JBig2_Result::kFailure;
953 }
954 }
955 }
956 pGRD->USESKIP = 0;
957 m_pGRD = std::move(pGRD);
958 }
959 pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
960 if (m_pGRD->MMR == 0) {
961 if (m_gbContext.empty())
962 m_gbContext.resize(GetHuffContextSize(m_pGRD->GBTEMPLATE));
963
964 bool bStart = !m_pArithDecoder;
965 if (bStart) {
966 m_pArithDecoder = std::make_unique<CJBig2_ArithDecoder>(m_pStream.get());
967 }
968 {
969 // |state.gbContext| can't exist when m_gbContext.clear() called below.
970 CJBig2_GRDProc::ProgressiveArithDecodeState state;
971 state.pImage = &pSegment->m_Image;
972 state.pArithDecoder = m_pArithDecoder.get();
973 state.gbContext = m_gbContext.data();
974 state.pPause = pPause;
975 m_ProcessingStatus = bStart ? m_pGRD->StartDecodeArith(&state)
976 : m_pGRD->ContinueDecode(&state);
977 if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
978 if (pSegment->m_cFlags.s.type != 36) {
979 if (!m_bBufSpecified) {
980 const auto& pPageInfo = m_PageInfoList.back();
981 if ((pPageInfo->m_bIsStriped == 1) &&
982 (m_ri.y + m_ri.height > m_pPage->height())) {
983 m_pPage->Expand(m_ri.y + m_ri.height,
984 (pPageInfo->m_cFlags & 4) ? 1 : 0);
985 }
986 }
987 const FX_RECT& rect = m_pGRD->GetReplaceRect();
988 m_pPage->ComposeFromWithRect(m_ri.x + rect.left, m_ri.y + rect.top,
989 pSegment->m_Image.get(), rect,
990 (JBig2ComposeOp)(m_ri.flags & 0x03));
991 }
992 return JBig2_Result::kSuccess;
993 }
994 }
995 m_pArithDecoder.reset();
996 m_gbContext.clear();
997 if (!pSegment->m_Image) {
998 m_ProcessingStatus = FXCODEC_STATUS_ERROR;
999 m_pGRD.reset();
1000 return JBig2_Result::kFailure;
1001 }
1002 m_pStream->alignByte();
1003 m_pStream->offset(2);
1004 } else {
1005 m_pGRD->StartDecodeMMR(&pSegment->m_Image, m_pStream.get());
1006 if (!pSegment->m_Image) {
1007 m_pGRD.reset();
1008 return JBig2_Result::kFailure;
1009 }
1010 m_pStream->alignByte();
1011 }
1012 if (pSegment->m_cFlags.s.type != 36) {
1013 if (!m_bBufSpecified) {
1014 JBig2PageInfo* pPageInfo = m_PageInfoList.back().get();
1015 if ((pPageInfo->m_bIsStriped == 1) &&
1016 (m_ri.y + m_ri.height > m_pPage->height())) {
1017 m_pPage->Expand(m_ri.y + m_ri.height,
1018 (pPageInfo->m_cFlags & 4) ? 1 : 0);
1019 }
1020 }
1021 const FX_RECT& rect = m_pGRD->GetReplaceRect();
1022 m_pPage->ComposeFromWithRect(m_ri.x + rect.left, m_ri.y + rect.top,
1023 pSegment->m_Image.get(), rect,
1024 (JBig2ComposeOp)(m_ri.flags & 0x03));
1025 pSegment->m_Image.reset();
1026 }
1027 m_pGRD.reset();
1028 return JBig2_Result::kSuccess;
1029 }
1030
ParseGenericRefinementRegion(CJBig2_Segment * pSegment)1031 JBig2_Result CJBig2_Context::ParseGenericRefinementRegion(
1032 CJBig2_Segment* pSegment) {
1033 JBig2RegionInfo ri;
1034 uint8_t cFlags;
1035 if (ParseRegionInfo(&ri) != JBig2_Result::kSuccess ||
1036 m_pStream->read1Byte(&cFlags) != 0) {
1037 return JBig2_Result::kFailure;
1038 }
1039 if (!CJBig2_Image::IsValidImageSize(ri.width, ri.height))
1040 return JBig2_Result::kFailure;
1041
1042 auto pGRRD = std::make_unique<CJBig2_GRRDProc>();
1043 pGRRD->GRW = ri.width;
1044 pGRRD->GRH = ri.height;
1045 pGRRD->GRTEMPLATE = !!(cFlags & 0x01);
1046 pGRRD->TPGRON = (cFlags >> 1) & 0x01;
1047 if (!pGRRD->GRTEMPLATE) {
1048 for (int32_t i = 0; i < 4; ++i) {
1049 if (m_pStream->read1Byte((uint8_t*)&pGRRD->GRAT[i]) != 0)
1050 return JBig2_Result::kFailure;
1051 }
1052 }
1053 CJBig2_Segment* pSeg = nullptr;
1054 if (pSegment->m_nReferred_to_segment_count > 0) {
1055 int32_t i;
1056 for (i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
1057 pSeg = FindSegmentByNumber(pSegment->m_Referred_to_segment_numbers[0]);
1058 if (!pSeg)
1059 return JBig2_Result::kFailure;
1060
1061 if (pSeg->m_cFlags.s.type == 4 || pSeg->m_cFlags.s.type == 20 ||
1062 pSeg->m_cFlags.s.type == 36 || pSeg->m_cFlags.s.type == 40) {
1063 break;
1064 }
1065 }
1066 if (i >= pSegment->m_nReferred_to_segment_count)
1067 return JBig2_Result::kFailure;
1068
1069 pGRRD->GRREFERENCE = pSeg->m_Image.get();
1070 } else {
1071 pGRRD->GRREFERENCE = m_pPage.get();
1072 }
1073 pGRRD->GRREFERENCEDX = 0;
1074 pGRRD->GRREFERENCEDY = 0;
1075 const size_t size = GetRefAggContextSize(pGRRD->GRTEMPLATE);
1076 std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> grContext(
1077 FX_Alloc(JBig2ArithCtx, size));
1078 auto pArithDecoder = std::make_unique<CJBig2_ArithDecoder>(m_pStream.get());
1079 pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1080 pSegment->m_Image = pGRRD->Decode(pArithDecoder.get(), grContext.get());
1081 if (!pSegment->m_Image)
1082 return JBig2_Result::kFailure;
1083
1084 m_pStream->alignByte();
1085 m_pStream->offset(2);
1086 if (pSegment->m_cFlags.s.type != 40) {
1087 if (!m_bBufSpecified) {
1088 JBig2PageInfo* pPageInfo = m_PageInfoList.back().get();
1089 if ((pPageInfo->m_bIsStriped == 1) &&
1090 (ri.y + ri.height > m_pPage->height())) {
1091 m_pPage->Expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1092 }
1093 }
1094 m_pPage->ComposeFrom(ri.x, ri.y, pSegment->m_Image.get(),
1095 (JBig2ComposeOp)(ri.flags & 0x03));
1096 pSegment->m_Image.reset();
1097 }
1098 return JBig2_Result::kSuccess;
1099 }
1100
ParseTable(CJBig2_Segment * pSegment)1101 JBig2_Result CJBig2_Context::ParseTable(CJBig2_Segment* pSegment) {
1102 pSegment->m_nResultType = JBIG2_HUFFMAN_TABLE_POINTER;
1103 pSegment->m_HuffmanTable.reset();
1104 auto pHuff = std::make_unique<CJBig2_HuffmanTable>(m_pStream.get());
1105 if (!pHuff->IsOK())
1106 return JBig2_Result::kFailure;
1107
1108 pSegment->m_HuffmanTable = std::move(pHuff);
1109 m_pStream->alignByte();
1110 return JBig2_Result::kSuccess;
1111 }
1112
ParseRegionInfo(JBig2RegionInfo * pRI)1113 JBig2_Result CJBig2_Context::ParseRegionInfo(JBig2RegionInfo* pRI) {
1114 if (m_pStream->readInteger((uint32_t*)&pRI->width) != 0 ||
1115 m_pStream->readInteger((uint32_t*)&pRI->height) != 0 ||
1116 m_pStream->readInteger((uint32_t*)&pRI->x) != 0 ||
1117 m_pStream->readInteger((uint32_t*)&pRI->y) != 0 ||
1118 m_pStream->read1Byte(&pRI->flags) != 0) {
1119 return JBig2_Result::kFailure;
1120 }
1121 return JBig2_Result::kSuccess;
1122 }
1123
DecodeSymbolIDHuffmanTable(uint32_t SBNUMSYMS)1124 std::vector<JBig2HuffmanCode> CJBig2_Context::DecodeSymbolIDHuffmanTable(
1125 uint32_t SBNUMSYMS) {
1126 const size_t kRunCodesSize = 35;
1127 JBig2HuffmanCode huffman_codes[kRunCodesSize];
1128 for (size_t i = 0; i < kRunCodesSize; ++i) {
1129 if (m_pStream->readNBits(4, &huffman_codes[i].codelen) != 0)
1130 return std::vector<JBig2HuffmanCode>();
1131 }
1132 if (!HuffmanAssignCode(huffman_codes, kRunCodesSize))
1133 return std::vector<JBig2HuffmanCode>();
1134
1135 std::vector<JBig2HuffmanCode> SBSYMCODES(SBNUMSYMS);
1136 int32_t run = 0;
1137 int32_t i = 0;
1138 while (i < static_cast<int>(SBNUMSYMS)) {
1139 size_t j;
1140 FX_SAFE_INT32 nSafeVal = 0;
1141 int32_t nBits = 0;
1142 uint32_t nTemp;
1143 while (true) {
1144 if (m_pStream->read1Bit(&nTemp) != 0)
1145 return std::vector<JBig2HuffmanCode>();
1146
1147 nSafeVal <<= 1;
1148 if (!nSafeVal.IsValid())
1149 return std::vector<JBig2HuffmanCode>();
1150
1151 nSafeVal |= nTemp;
1152 ++nBits;
1153 const int32_t nVal = nSafeVal.ValueOrDie();
1154 for (j = 0; j < kRunCodesSize; ++j) {
1155 if (nBits == huffman_codes[j].codelen && nVal == huffman_codes[j].code)
1156 break;
1157 }
1158 if (j < kRunCodesSize)
1159 break;
1160 }
1161 int32_t runcode = static_cast<int32_t>(j);
1162 if (runcode < 32) {
1163 SBSYMCODES[i].codelen = runcode;
1164 run = 0;
1165 } else if (runcode == 32) {
1166 if (m_pStream->readNBits(2, &nTemp) != 0)
1167 return std::vector<JBig2HuffmanCode>();
1168 run = nTemp + 3;
1169 } else if (runcode == 33) {
1170 if (m_pStream->readNBits(3, &nTemp) != 0)
1171 return std::vector<JBig2HuffmanCode>();
1172 run = nTemp + 3;
1173 } else if (runcode == 34) {
1174 if (m_pStream->readNBits(7, &nTemp) != 0)
1175 return std::vector<JBig2HuffmanCode>();
1176 run = nTemp + 11;
1177 }
1178 if (run > 0) {
1179 if (i + run > (int)SBNUMSYMS)
1180 return std::vector<JBig2HuffmanCode>();
1181 for (int32_t k = 0; k < run; ++k) {
1182 if (runcode == 32 && i > 0)
1183 SBSYMCODES[i + k].codelen = SBSYMCODES[i - 1].codelen;
1184 else
1185 SBSYMCODES[i + k].codelen = 0;
1186 }
1187 i += run;
1188 } else {
1189 ++i;
1190 }
1191 }
1192 if (!HuffmanAssignCode(SBSYMCODES.data(), SBNUMSYMS))
1193 return std::vector<JBig2HuffmanCode>();
1194 return SBSYMCODES;
1195 }
1196
GetHuffmanTable(size_t idx)1197 const CJBig2_HuffmanTable* CJBig2_Context::GetHuffmanTable(size_t idx) {
1198 ASSERT(idx > 0);
1199 ASSERT(idx < CJBig2_HuffmanTable::kNumHuffmanTables);
1200 if (!m_HuffmanTables[idx].get())
1201 m_HuffmanTables[idx] = std::make_unique<CJBig2_HuffmanTable>(idx);
1202 return m_HuffmanTables[idx].get();
1203 }
1204
1205 // static
HuffmanAssignCode(JBig2HuffmanCode * SBSYMCODES,uint32_t NTEMP)1206 bool CJBig2_Context::HuffmanAssignCode(JBig2HuffmanCode* SBSYMCODES,
1207 uint32_t NTEMP) {
1208 int LENMAX = 0;
1209 for (uint32_t i = 0; i < NTEMP; ++i)
1210 LENMAX = std::max(SBSYMCODES[i].codelen, LENMAX);
1211
1212 std::vector<int> LENCOUNT(LENMAX + 1);
1213 std::vector<int> FIRSTCODE(LENMAX + 1);
1214 for (uint32_t i = 0; i < NTEMP; ++i)
1215 ++LENCOUNT[SBSYMCODES[i].codelen];
1216 LENCOUNT[0] = 0;
1217
1218 for (int i = 1; i <= LENMAX; ++i) {
1219 FX_SAFE_INT32 shifted = FIRSTCODE[i - 1];
1220 shifted += LENCOUNT[i - 1];
1221 shifted <<= 1;
1222 if (!shifted.IsValid())
1223 return false;
1224
1225 FIRSTCODE[i] = shifted.ValueOrDie();
1226 int CURCODE = FIRSTCODE[i];
1227 for (uint32_t j = 0; j < NTEMP; ++j) {
1228 if (SBSYMCODES[j].codelen == i)
1229 SBSYMCODES[j].code = CURCODE++;
1230 }
1231 }
1232 return true;
1233 }
1234