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