• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fxcodec/jbig2/JBig2_Context.h"
8 
9 #include <algorithm>
10 #include <list>
11 #include <utility>
12 #include <vector>
13 
14 #include "core/fpdfapi/parser/cpdf_stream.h"
15 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
16 #include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
17 #include "core/fxcodec/jbig2/JBig2_BitStream.h"
18 #include "core/fxcodec/jbig2/JBig2_GrdProc.h"
19 #include "core/fxcodec/jbig2/JBig2_GrrdProc.h"
20 #include "core/fxcodec/jbig2/JBig2_HtrdProc.h"
21 #include "core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h"
22 #include "core/fxcodec/jbig2/JBig2_PddProc.h"
23 #include "core/fxcodec/jbig2/JBig2_SddProc.h"
24 #include "core/fxcodec/jbig2/JBig2_TrdProc.h"
25 #include "third_party/base/ptr_util.h"
26 #include "third_party/base/stl_util.h"
27 
28 namespace {
29 
GetHuffContextSize(uint8_t val)30 size_t GetHuffContextSize(uint8_t val) {
31   return val == 0 ? 65536 : val == 1 ? 8192 : 1024;
32 }
33 
GetRefAggContextSize(bool val)34 size_t GetRefAggContextSize(bool val) {
35   return val ? 1024 : 8192;
36 }
37 
38 }  // namespace
39 
40 // Implement a very small least recently used (LRU) cache. It is very
41 // common for a JBIG2 dictionary to span multiple pages in a PDF file,
42 // and we do not want to decode the same dictionary over and over
43 // again. We key off of the memory location of the dictionary. The
44 // list keeps track of the freshness of entries, with freshest ones
45 // at the front. Even a tiny cache size like 2 makes a dramatic
46 // difference for typical JBIG2 documents.
47 static const int kSymbolDictCacheMaxSize = 2;
48 
CJBig2_Context(CPDF_StreamAcc * pGlobalStream,CPDF_StreamAcc * pSrcStream,std::list<CJBig2_CachePair> * pSymbolDictCache,IFX_Pause * pPause,bool bIsGlobal)49 CJBig2_Context::CJBig2_Context(CPDF_StreamAcc* pGlobalStream,
50                                CPDF_StreamAcc* pSrcStream,
51                                std::list<CJBig2_CachePair>* pSymbolDictCache,
52                                IFX_Pause* pPause,
53                                bool bIsGlobal)
54     : m_nSegmentDecoded(0),
55       m_bInPage(false),
56       m_bBufSpecified(false),
57       m_PauseStep(10),
58       m_pPause(pPause),
59       m_ProcessingStatus(FXCODEC_STATUS_FRAME_READY),
60       m_dwOffset(0),
61       m_pSymbolDictCache(pSymbolDictCache),
62       m_bIsGlobal(bIsGlobal) {
63   if (pGlobalStream && (pGlobalStream->GetSize() > 0)) {
64     m_pGlobalContext = pdfium::MakeUnique<CJBig2_Context>(
65         nullptr, pGlobalStream, pSymbolDictCache, pPause, true);
66   }
67   m_pStream = pdfium::MakeUnique<CJBig2_BitStream>(pSrcStream);
68 }
69 
~CJBig2_Context()70 CJBig2_Context::~CJBig2_Context() {}
71 
decode_SquentialOrgnazation(IFX_Pause * pPause)72 int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) {
73   int32_t nRet;
74   if (m_pStream->getByteLeft() <= 0)
75     return JBIG2_END_OF_FILE;
76 
77   while (m_pStream->getByteLeft() >= JBIG2_MIN_SEGMENT_SIZE) {
78     if (!m_pSegment) {
79       m_pSegment = pdfium::MakeUnique<CJBig2_Segment>();
80       nRet = parseSegmentHeader(m_pSegment.get());
81       if (nRet != JBIG2_SUCCESS) {
82         m_pSegment.reset();
83         return nRet;
84       }
85       m_dwOffset = m_pStream->getOffset();
86     }
87     nRet = parseSegmentData(m_pSegment.get(), pPause);
88     if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
89       m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
90       m_PauseStep = 2;
91       return JBIG2_SUCCESS;
92     }
93     if (nRet == JBIG2_END_OF_PAGE || nRet == JBIG2_END_OF_FILE) {
94       m_pSegment.reset();
95       return JBIG2_SUCCESS;
96     }
97     if (nRet != JBIG2_SUCCESS) {
98       m_pSegment.reset();
99       return nRet;
100     }
101     if (m_pSegment->m_dwData_length != 0xffffffff) {
102       m_dwOffset += m_pSegment->m_dwData_length;
103       m_pStream->setOffset(m_dwOffset);
104     } else {
105       m_pStream->offset(4);
106     }
107     m_SegmentList.push_back(std::move(m_pSegment));
108     if (m_pStream->getByteLeft() > 0 && m_pPage && pPause &&
109         pPause->NeedToPauseNow()) {
110       m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
111       m_PauseStep = 2;
112       return JBIG2_SUCCESS;
113     }
114   }
115   return JBIG2_SUCCESS;
116 }
117 
decode_EmbedOrgnazation(IFX_Pause * pPause)118 int32_t CJBig2_Context::decode_EmbedOrgnazation(IFX_Pause* pPause) {
119   return decode_SquentialOrgnazation(pPause);
120 }
121 
decode_RandomOrgnazation_FirstPage(IFX_Pause * pPause)122 int32_t CJBig2_Context::decode_RandomOrgnazation_FirstPage(IFX_Pause* pPause) {
123   int32_t nRet;
124   while (m_pStream->getByteLeft() > JBIG2_MIN_SEGMENT_SIZE) {
125     std::unique_ptr<CJBig2_Segment> pSegment(new CJBig2_Segment);
126     nRet = parseSegmentHeader(pSegment.get());
127     if (nRet != JBIG2_SUCCESS) {
128       return nRet;
129     } else if (pSegment->m_cFlags.s.type == 51) {
130       break;
131     }
132     m_SegmentList.push_back(std::move(pSegment));
133     if (pPause && m_pPause && pPause->NeedToPauseNow()) {
134       m_PauseStep = 3;
135       m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
136       return JBIG2_SUCCESS;
137     }
138   }
139   m_nSegmentDecoded = 0;
140   return decode_RandomOrgnazation(pPause);
141 }
142 
decode_RandomOrgnazation(IFX_Pause * pPause)143 int32_t CJBig2_Context::decode_RandomOrgnazation(IFX_Pause* pPause) {
144   for (; m_nSegmentDecoded < m_SegmentList.size(); ++m_nSegmentDecoded) {
145     int32_t nRet =
146         parseSegmentData(m_SegmentList[m_nSegmentDecoded].get(), pPause);
147     if (nRet == JBIG2_END_OF_PAGE || nRet == JBIG2_END_OF_FILE)
148       return JBIG2_SUCCESS;
149 
150     if (nRet != JBIG2_SUCCESS)
151       return nRet;
152 
153     if (m_pPage && pPause && pPause->NeedToPauseNow()) {
154       m_PauseStep = 4;
155       m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
156       return JBIG2_SUCCESS;
157     }
158   }
159   return JBIG2_SUCCESS;
160 }
161 
getFirstPage(uint8_t * pBuf,int32_t width,int32_t height,int32_t stride,IFX_Pause * pPause)162 int32_t CJBig2_Context::getFirstPage(uint8_t* pBuf,
163                                      int32_t width,
164                                      int32_t height,
165                                      int32_t stride,
166                                      IFX_Pause* pPause) {
167   int32_t nRet = 0;
168   if (m_pGlobalContext) {
169     nRet = m_pGlobalContext->decode_EmbedOrgnazation(pPause);
170     if (nRet != JBIG2_SUCCESS) {
171       m_ProcessingStatus = FXCODEC_STATUS_ERROR;
172       return nRet;
173     }
174   }
175   m_PauseStep = 0;
176   m_pPage = pdfium::MakeUnique<CJBig2_Image>(width, height, stride, pBuf);
177   m_bBufSpecified = true;
178   if (pPause && pPause->NeedToPauseNow()) {
179     m_PauseStep = 1;
180     m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
181     return nRet;
182   }
183   return Continue(pPause);
184 }
185 
Continue(IFX_Pause * pPause)186 int32_t CJBig2_Context::Continue(IFX_Pause* pPause) {
187   m_ProcessingStatus = FXCODEC_STATUS_DECODE_READY;
188   int32_t nRet = 0;
189   if (m_PauseStep <= 1) {
190     nRet = decode_EmbedOrgnazation(pPause);
191   } else if (m_PauseStep == 2) {
192     nRet = decode_SquentialOrgnazation(pPause);
193   } else if (m_PauseStep == 3) {
194     nRet = decode_RandomOrgnazation_FirstPage(pPause);
195   } else if (m_PauseStep == 4) {
196     nRet = decode_RandomOrgnazation(pPause);
197   } else if (m_PauseStep == 5) {
198     m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH;
199     return JBIG2_SUCCESS;
200   }
201   if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
202     return nRet;
203   }
204   m_PauseStep = 5;
205   if (!m_bBufSpecified && nRet == JBIG2_SUCCESS) {
206     m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH;
207     return JBIG2_SUCCESS;
208   }
209   if (nRet == JBIG2_SUCCESS) {
210     m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH;
211   } else {
212     m_ProcessingStatus = FXCODEC_STATUS_ERROR;
213   }
214   return nRet;
215 }
216 
findSegmentByNumber(uint32_t dwNumber)217 CJBig2_Segment* CJBig2_Context::findSegmentByNumber(uint32_t dwNumber) {
218   if (m_pGlobalContext) {
219     CJBig2_Segment* pSeg = m_pGlobalContext->findSegmentByNumber(dwNumber);
220     if (pSeg) {
221       return pSeg;
222     }
223   }
224   for (const auto& pSeg : m_SegmentList) {
225     if (pSeg->m_dwNumber == dwNumber)
226       return pSeg.get();
227   }
228   return nullptr;
229 }
230 
findReferredSegmentByTypeAndIndex(CJBig2_Segment * pSegment,uint8_t cType,int32_t nIndex)231 CJBig2_Segment* CJBig2_Context::findReferredSegmentByTypeAndIndex(
232     CJBig2_Segment* pSegment,
233     uint8_t cType,
234     int32_t nIndex) {
235   int32_t count = 0;
236   for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
237     CJBig2_Segment* pSeg =
238         findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
239     if (pSeg && pSeg->m_cFlags.s.type == cType) {
240       if (count == nIndex)
241         return pSeg;
242       ++count;
243     }
244   }
245   return nullptr;
246 }
247 
parseSegmentHeader(CJBig2_Segment * pSegment)248 int32_t CJBig2_Context::parseSegmentHeader(CJBig2_Segment* pSegment) {
249   if (m_pStream->readInteger(&pSegment->m_dwNumber) != 0 ||
250       m_pStream->read1Byte(&pSegment->m_cFlags.c) != 0) {
251     return JBIG2_ERROR_TOO_SHORT;
252   }
253 
254   uint32_t dwTemp;
255   uint8_t cTemp = m_pStream->getCurByte();
256   if ((cTemp >> 5) == 7) {
257     if (m_pStream->readInteger(
258             (uint32_t*)&pSegment->m_nReferred_to_segment_count) != 0) {
259       return JBIG2_ERROR_TOO_SHORT;
260     }
261     pSegment->m_nReferred_to_segment_count &= 0x1fffffff;
262     if (pSegment->m_nReferred_to_segment_count >
263         JBIG2_MAX_REFERRED_SEGMENT_COUNT) {
264       return JBIG2_ERROR_LIMIT;
265     }
266     dwTemp = 5 + 4 + (pSegment->m_nReferred_to_segment_count + 1) / 8;
267   } else {
268     if (m_pStream->read1Byte(&cTemp) != 0)
269       return JBIG2_ERROR_TOO_SHORT;
270 
271     pSegment->m_nReferred_to_segment_count = cTemp >> 5;
272     dwTemp = 5 + 1;
273   }
274   uint8_t cSSize =
275       pSegment->m_dwNumber > 65536 ? 4 : pSegment->m_dwNumber > 256 ? 2 : 1;
276   uint8_t cPSize = pSegment->m_cFlags.s.page_association_size ? 4 : 1;
277   if (pSegment->m_nReferred_to_segment_count) {
278     pSegment->m_pReferred_to_segment_numbers =
279         FX_Alloc(uint32_t, pSegment->m_nReferred_to_segment_count);
280     for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
281       switch (cSSize) {
282         case 1:
283           if (m_pStream->read1Byte(&cTemp) != 0)
284             return JBIG2_ERROR_TOO_SHORT;
285 
286           pSegment->m_pReferred_to_segment_numbers[i] = cTemp;
287           break;
288         case 2:
289           uint16_t wTemp;
290           if (m_pStream->readShortInteger(&wTemp) != 0)
291             return JBIG2_ERROR_TOO_SHORT;
292 
293           pSegment->m_pReferred_to_segment_numbers[i] = wTemp;
294           break;
295         case 4:
296           if (m_pStream->readInteger(&dwTemp) != 0)
297             return JBIG2_ERROR_TOO_SHORT;
298 
299           pSegment->m_pReferred_to_segment_numbers[i] = dwTemp;
300           break;
301       }
302       if (pSegment->m_pReferred_to_segment_numbers[i] >= pSegment->m_dwNumber)
303         return JBIG2_ERROR_TOO_SHORT;
304     }
305   }
306   if (cPSize == 1) {
307     if (m_pStream->read1Byte(&cTemp) != 0)
308       return JBIG2_ERROR_TOO_SHORT;
309     pSegment->m_dwPage_association = cTemp;
310   } else {
311     if (m_pStream->readInteger(&pSegment->m_dwPage_association) != 0) {
312       return JBIG2_ERROR_TOO_SHORT;
313     }
314   }
315   if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0)
316     return JBIG2_ERROR_TOO_SHORT;
317 
318   pSegment->m_dwObjNum = m_pStream->getObjNum();
319   pSegment->m_dwDataOffset = m_pStream->getOffset();
320   pSegment->m_State = JBIG2_SEGMENT_DATA_UNPARSED;
321   return JBIG2_SUCCESS;
322 }
323 
parseSegmentData(CJBig2_Segment * pSegment,IFX_Pause * pPause)324 int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment,
325                                          IFX_Pause* pPause) {
326   int32_t ret = ProcessingParseSegmentData(pSegment, pPause);
327   while (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE &&
328          m_pStream->getByteLeft() > 0) {
329     ret = ProcessingParseSegmentData(pSegment, pPause);
330   }
331   return ret;
332 }
333 
ProcessingParseSegmentData(CJBig2_Segment * pSegment,IFX_Pause * pPause)334 int32_t CJBig2_Context::ProcessingParseSegmentData(CJBig2_Segment* pSegment,
335                                                    IFX_Pause* pPause) {
336   switch (pSegment->m_cFlags.s.type) {
337     case 0:
338       return parseSymbolDict(pSegment, pPause);
339     case 4:
340     case 6:
341     case 7:
342       if (!m_bInPage)
343         return JBIG2_ERROR_FATAL;
344       return parseTextRegion(pSegment);
345     case 16:
346       return parsePatternDict(pSegment, pPause);
347     case 20:
348     case 22:
349     case 23:
350       if (!m_bInPage)
351         return JBIG2_ERROR_FATAL;
352       return parseHalftoneRegion(pSegment, pPause);
353     case 36:
354     case 38:
355     case 39:
356       if (!m_bInPage)
357         return JBIG2_ERROR_FATAL;
358       return parseGenericRegion(pSegment, pPause);
359     case 40:
360     case 42:
361     case 43:
362       if (!m_bInPage)
363         return JBIG2_ERROR_FATAL;
364       return parseGenericRefinementRegion(pSegment);
365     case 48: {
366       uint16_t wTemp;
367       std::unique_ptr<JBig2PageInfo> pPageInfo(new JBig2PageInfo);
368       if (m_pStream->readInteger(&pPageInfo->m_dwWidth) != 0 ||
369           m_pStream->readInteger(&pPageInfo->m_dwHeight) != 0 ||
370           m_pStream->readInteger(&pPageInfo->m_dwResolutionX) != 0 ||
371           m_pStream->readInteger(&pPageInfo->m_dwResolutionY) != 0 ||
372           m_pStream->read1Byte(&pPageInfo->m_cFlags) != 0 ||
373           m_pStream->readShortInteger(&wTemp) != 0) {
374         return JBIG2_ERROR_TOO_SHORT;
375       }
376       pPageInfo->m_bIsStriped = !!(wTemp & 0x8000);
377       pPageInfo->m_wMaxStripeSize = wTemp & 0x7fff;
378       bool bMaxHeight = (pPageInfo->m_dwHeight == 0xffffffff);
379       if (bMaxHeight && pPageInfo->m_bIsStriped != true)
380         pPageInfo->m_bIsStriped = true;
381 
382       if (!m_bBufSpecified) {
383         uint32_t height =
384             bMaxHeight ? pPageInfo->m_wMaxStripeSize : pPageInfo->m_dwHeight;
385         m_pPage =
386             pdfium::MakeUnique<CJBig2_Image>(pPageInfo->m_dwWidth, height);
387       }
388 
389       if (!m_pPage->m_pData) {
390         m_ProcessingStatus = FXCODEC_STATUS_ERROR;
391         return JBIG2_ERROR_TOO_SHORT;
392       }
393 
394       m_pPage->fill((pPageInfo->m_cFlags & 4) ? 1 : 0);
395       m_PageInfoList.push_back(std::move(pPageInfo));
396       m_bInPage = true;
397     } break;
398     case 49:
399       m_bInPage = false;
400       return JBIG2_END_OF_PAGE;
401       break;
402     case 50:
403       m_pStream->offset(pSegment->m_dwData_length);
404       break;
405     case 51:
406       return JBIG2_END_OF_FILE;
407     case 52:
408       m_pStream->offset(pSegment->m_dwData_length);
409       break;
410     case 53:
411       return parseTable(pSegment);
412     case 62:
413       m_pStream->offset(pSegment->m_dwData_length);
414       break;
415     default:
416       break;
417   }
418   return JBIG2_SUCCESS;
419 }
420 
parseSymbolDict(CJBig2_Segment * pSegment,IFX_Pause * pPause)421 int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment,
422                                         IFX_Pause* pPause) {
423   uint16_t wFlags;
424   if (m_pStream->readShortInteger(&wFlags) != 0)
425     return JBIG2_ERROR_TOO_SHORT;
426 
427   std::unique_ptr<CJBig2_SDDProc> pSymbolDictDecoder(new CJBig2_SDDProc);
428   pSymbolDictDecoder->SDHUFF = wFlags & 0x0001;
429   pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001;
430   pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003;
431   pSymbolDictDecoder->SDRTEMPLATE = !!((wFlags >> 12) & 0x0003);
432   uint8_t cSDHUFFDH = (wFlags >> 2) & 0x0003;
433   uint8_t cSDHUFFDW = (wFlags >> 4) & 0x0003;
434   uint8_t cSDHUFFBMSIZE = (wFlags >> 6) & 0x0001;
435   uint8_t cSDHUFFAGGINST = (wFlags >> 7) & 0x0001;
436   if (pSymbolDictDecoder->SDHUFF == 0) {
437     const uint32_t dwTemp = (pSymbolDictDecoder->SDTEMPLATE == 0) ? 8 : 2;
438     for (uint32_t i = 0; i < dwTemp; ++i) {
439       if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDAT[i]) != 0)
440         return JBIG2_ERROR_TOO_SHORT;
441     }
442   }
443   if (pSymbolDictDecoder->SDREFAGG == 1 && !pSymbolDictDecoder->SDRTEMPLATE) {
444     for (int32_t i = 0; i < 4; ++i) {
445       if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDRAT[i]) != 0)
446         return JBIG2_ERROR_TOO_SHORT;
447     }
448   }
449   if (m_pStream->readInteger(&pSymbolDictDecoder->SDNUMEXSYMS) != 0 ||
450       m_pStream->readInteger(&pSymbolDictDecoder->SDNUMNEWSYMS) != 0) {
451     return JBIG2_ERROR_TOO_SHORT;
452   }
453   if (pSymbolDictDecoder->SDNUMEXSYMS > JBIG2_MAX_EXPORT_SYSMBOLS ||
454       pSymbolDictDecoder->SDNUMNEWSYMS > JBIG2_MAX_NEW_SYSMBOLS) {
455     return JBIG2_ERROR_LIMIT;
456   }
457   for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
458     if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]))
459       return JBIG2_ERROR_FATAL;
460   }
461   CJBig2_Segment* pLRSeg = nullptr;
462   pSymbolDictDecoder->SDNUMINSYMS = 0;
463   for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
464     CJBig2_Segment* pSeg =
465         findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
466     if (pSeg->m_cFlags.s.type == 0) {
467       pSymbolDictDecoder->SDNUMINSYMS += pSeg->m_Result.sd->NumImages();
468       pLRSeg = pSeg;
469     }
470   }
471 
472   std::unique_ptr<CJBig2_Image*, FxFreeDeleter> SDINSYMS;
473   if (pSymbolDictDecoder->SDNUMINSYMS != 0) {
474     SDINSYMS.reset(FX_Alloc(CJBig2_Image*, pSymbolDictDecoder->SDNUMINSYMS));
475     uint32_t dwTemp = 0;
476     for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
477       CJBig2_Segment* pSeg =
478           findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
479       if (pSeg->m_cFlags.s.type == 0) {
480         const CJBig2_SymbolDict& dict = *pSeg->m_Result.sd;
481         for (size_t j = 0; j < dict.NumImages(); ++j)
482           SDINSYMS.get()[dwTemp + j] = dict.GetImage(j);
483         dwTemp += dict.NumImages();
484       }
485     }
486   }
487   pSymbolDictDecoder->SDINSYMS = SDINSYMS.get();
488 
489   std::unique_ptr<CJBig2_HuffmanTable> Table_B1;
490   std::unique_ptr<CJBig2_HuffmanTable> Table_B2;
491   std::unique_ptr<CJBig2_HuffmanTable> Table_B3;
492   std::unique_ptr<CJBig2_HuffmanTable> Table_B4;
493   std::unique_ptr<CJBig2_HuffmanTable> Table_B5;
494   if (pSymbolDictDecoder->SDHUFF == 1) {
495     if (cSDHUFFDH == 2 || cSDHUFFDW == 2)
496       return JBIG2_ERROR_FATAL;
497 
498     int32_t nIndex = 0;
499     if (cSDHUFFDH == 0) {
500       Table_B4 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
501           HuffmanTable_B4, HuffmanTable_B4_Size, HuffmanTable_HTOOB_B4);
502       pSymbolDictDecoder->SDHUFFDH = Table_B4.get();
503     } else if (cSDHUFFDH == 1) {
504       Table_B5 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
505           HuffmanTable_B5, HuffmanTable_B5_Size, HuffmanTable_HTOOB_B5);
506       pSymbolDictDecoder->SDHUFFDH = Table_B5.get();
507     } else {
508       CJBig2_Segment* pSeg =
509           findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
510       if (!pSeg)
511         return JBIG2_ERROR_FATAL;
512       pSymbolDictDecoder->SDHUFFDH = pSeg->m_Result.ht;
513     }
514     if (cSDHUFFDW == 0) {
515       Table_B2 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
516           HuffmanTable_B2, HuffmanTable_B2_Size, HuffmanTable_HTOOB_B2);
517       pSymbolDictDecoder->SDHUFFDW = Table_B2.get();
518     } else if (cSDHUFFDW == 1) {
519       Table_B3 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
520           HuffmanTable_B3, HuffmanTable_B3_Size, HuffmanTable_HTOOB_B3);
521       pSymbolDictDecoder->SDHUFFDW = Table_B3.get();
522     } else {
523       CJBig2_Segment* pSeg =
524           findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
525       if (!pSeg)
526         return JBIG2_ERROR_FATAL;
527       pSymbolDictDecoder->SDHUFFDW = pSeg->m_Result.ht;
528     }
529     if (cSDHUFFBMSIZE == 0) {
530       Table_B1 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
531           HuffmanTable_B1, HuffmanTable_B1_Size, HuffmanTable_HTOOB_B1);
532       pSymbolDictDecoder->SDHUFFBMSIZE = Table_B1.get();
533     } else {
534       CJBig2_Segment* pSeg =
535           findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
536       if (!pSeg)
537         return JBIG2_ERROR_FATAL;
538       pSymbolDictDecoder->SDHUFFBMSIZE = pSeg->m_Result.ht;
539     }
540     if (pSymbolDictDecoder->SDREFAGG == 1) {
541       if (cSDHUFFAGGINST == 0) {
542         if (!Table_B1) {
543           Table_B1 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
544               HuffmanTable_B1, HuffmanTable_B1_Size, HuffmanTable_HTOOB_B1);
545         }
546         pSymbolDictDecoder->SDHUFFAGGINST = Table_B1.get();
547       } else {
548         CJBig2_Segment* pSeg =
549             findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
550         if (!pSeg)
551           return JBIG2_ERROR_FATAL;
552         pSymbolDictDecoder->SDHUFFAGGINST = pSeg->m_Result.ht;
553       }
554     }
555   }
556 
557   const bool bUseGbContext = (pSymbolDictDecoder->SDHUFF == 0);
558   const bool bUseGrContext = (pSymbolDictDecoder->SDREFAGG == 1);
559   const size_t gbContextSize =
560       GetHuffContextSize(pSymbolDictDecoder->SDTEMPLATE);
561   const size_t grContextSize =
562       GetRefAggContextSize(pSymbolDictDecoder->SDRTEMPLATE);
563   std::vector<JBig2ArithCtx> gbContext;
564   std::vector<JBig2ArithCtx> grContext;
565   if ((wFlags & 0x0100) && pLRSeg) {
566     if (bUseGbContext) {
567       gbContext = pLRSeg->m_Result.sd->GbContext();
568       if (gbContext.size() != gbContextSize)
569         return JBIG2_ERROR_FATAL;
570     }
571     if (bUseGrContext) {
572       grContext = pLRSeg->m_Result.sd->GrContext();
573       if (grContext.size() != grContextSize)
574         return JBIG2_ERROR_FATAL;
575     }
576   } else {
577     if (bUseGbContext)
578       gbContext.resize(gbContextSize);
579     if (bUseGrContext)
580       grContext.resize(grContextSize);
581   }
582 
583   CJBig2_CacheKey key =
584       CJBig2_CacheKey(pSegment->m_dwObjNum, pSegment->m_dwDataOffset);
585   bool cache_hit = false;
586   pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER;
587   if (m_bIsGlobal && key.first != 0) {
588     for (auto it = m_pSymbolDictCache->begin(); it != m_pSymbolDictCache->end();
589          ++it) {
590       if (it->first == key) {
591         std::unique_ptr<CJBig2_SymbolDict> copy(it->second->DeepCopy());
592         pSegment->m_Result.sd = copy.release();
593         m_pSymbolDictCache->push_front(
594             CJBig2_CachePair(key, std::move(it->second)));
595         m_pSymbolDictCache->erase(it);
596         cache_hit = true;
597         break;
598       }
599     }
600   }
601   if (!cache_hit) {
602     if (bUseGbContext) {
603       std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
604           new CJBig2_ArithDecoder(m_pStream.get()));
605       pSegment->m_Result.sd = pSymbolDictDecoder->decode_Arith(
606           pArithDecoder.get(), &gbContext, &grContext);
607       if (!pSegment->m_Result.sd)
608         return JBIG2_ERROR_FATAL;
609 
610       m_pStream->alignByte();
611       m_pStream->offset(2);
612     } else {
613       pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(
614           m_pStream.get(), &gbContext, &grContext, pPause);
615       if (!pSegment->m_Result.sd)
616         return JBIG2_ERROR_FATAL;
617       m_pStream->alignByte();
618     }
619     if (m_bIsGlobal) {
620       std::unique_ptr<CJBig2_SymbolDict> value =
621           pSegment->m_Result.sd->DeepCopy();
622       int size = pdfium::CollectionSize<int>(*m_pSymbolDictCache);
623       while (size >= kSymbolDictCacheMaxSize) {
624         m_pSymbolDictCache->pop_back();
625         --size;
626       }
627       m_pSymbolDictCache->push_front(CJBig2_CachePair(key, std::move(value)));
628     }
629   }
630   if (wFlags & 0x0200) {
631     if (bUseGbContext)
632       pSegment->m_Result.sd->SetGbContext(gbContext);
633     if (bUseGrContext)
634       pSegment->m_Result.sd->SetGrContext(grContext);
635   }
636   return JBIG2_SUCCESS;
637 }
638 
parseTextRegion(CJBig2_Segment * pSegment)639 int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) {
640   uint16_t wFlags;
641   JBig2RegionInfo ri;
642   if (parseRegionInfo(&ri) != JBIG2_SUCCESS ||
643       m_pStream->readShortInteger(&wFlags) != 0) {
644     return JBIG2_ERROR_TOO_SHORT;
645   }
646 
647   std::unique_ptr<CJBig2_TRDProc> pTRD(new CJBig2_TRDProc);
648   pTRD->SBW = ri.width;
649   pTRD->SBH = ri.height;
650   pTRD->SBHUFF = wFlags & 0x0001;
651   pTRD->SBREFINE = (wFlags >> 1) & 0x0001;
652   uint32_t dwTemp = (wFlags >> 2) & 0x0003;
653   pTRD->SBSTRIPS = 1 << dwTemp;
654   pTRD->REFCORNER = (JBig2Corner)((wFlags >> 4) & 0x0003);
655   pTRD->TRANSPOSED = (wFlags >> 6) & 0x0001;
656   pTRD->SBCOMBOP = (JBig2ComposeOp)((wFlags >> 7) & 0x0003);
657   pTRD->SBDEFPIXEL = (wFlags >> 9) & 0x0001;
658   pTRD->SBDSOFFSET = (wFlags >> 10) & 0x001f;
659   if (pTRD->SBDSOFFSET >= 0x0010) {
660     pTRD->SBDSOFFSET = pTRD->SBDSOFFSET - 0x0020;
661   }
662   pTRD->SBRTEMPLATE = !!((wFlags >> 15) & 0x0001);
663 
664   uint8_t cSBHUFFFS = 0;
665   uint8_t cSBHUFFDS = 0;
666   uint8_t cSBHUFFDT = 0;
667   uint8_t cSBHUFFRDW = 0;
668   uint8_t cSBHUFFRDH = 0;
669   uint8_t cSBHUFFRDX = 0;
670   uint8_t cSBHUFFRDY = 0;
671   uint8_t cSBHUFFRSIZE = 0;
672   if (pTRD->SBHUFF == 1) {
673     if (m_pStream->readShortInteger(&wFlags) != 0)
674       return JBIG2_ERROR_TOO_SHORT;
675 
676     cSBHUFFFS = wFlags & 0x0003;
677     cSBHUFFDS = (wFlags >> 2) & 0x0003;
678     cSBHUFFDT = (wFlags >> 4) & 0x0003;
679     cSBHUFFRDW = (wFlags >> 6) & 0x0003;
680     cSBHUFFRDH = (wFlags >> 8) & 0x0003;
681     cSBHUFFRDX = (wFlags >> 10) & 0x0003;
682     cSBHUFFRDY = (wFlags >> 12) & 0x0003;
683     cSBHUFFRSIZE = (wFlags >> 14) & 0x0001;
684   }
685   if (pTRD->SBREFINE == 1 && !pTRD->SBRTEMPLATE) {
686     for (int32_t i = 0; i < 4; ++i) {
687       if (m_pStream->read1Byte((uint8_t*)&pTRD->SBRAT[i]) != 0)
688         return JBIG2_ERROR_TOO_SHORT;
689     }
690   }
691   if (m_pStream->readInteger(&pTRD->SBNUMINSTANCES) != 0)
692     return JBIG2_ERROR_TOO_SHORT;
693 
694   for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
695     if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]))
696       return JBIG2_ERROR_FATAL;
697   }
698 
699   pTRD->SBNUMSYMS = 0;
700   for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
701     CJBig2_Segment* pSeg =
702         findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
703     if (pSeg->m_cFlags.s.type == 0) {
704       pTRD->SBNUMSYMS += pSeg->m_Result.sd->NumImages();
705     }
706   }
707 
708   std::unique_ptr<CJBig2_Image*, FxFreeDeleter> SBSYMS;
709   if (pTRD->SBNUMSYMS > 0) {
710     SBSYMS.reset(FX_Alloc(CJBig2_Image*, pTRD->SBNUMSYMS));
711     dwTemp = 0;
712     for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
713       CJBig2_Segment* pSeg =
714           findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
715       if (pSeg->m_cFlags.s.type == 0) {
716         const CJBig2_SymbolDict& dict = *pSeg->m_Result.sd;
717         for (size_t j = 0; j < dict.NumImages(); ++j)
718           SBSYMS.get()[dwTemp + j] = dict.GetImage(j);
719         dwTemp += dict.NumImages();
720       }
721     }
722     pTRD->SBSYMS = SBSYMS.get();
723   } else {
724     pTRD->SBSYMS = nullptr;
725   }
726 
727   std::unique_ptr<JBig2HuffmanCode, FxFreeDeleter> SBSYMCODES;
728   if (pTRD->SBHUFF == 1) {
729     SBSYMCODES.reset(
730         decodeSymbolIDHuffmanTable(m_pStream.get(), pTRD->SBNUMSYMS));
731     if (!SBSYMCODES)
732       return JBIG2_ERROR_FATAL;
733 
734     m_pStream->alignByte();
735     pTRD->SBSYMCODES = SBSYMCODES.get();
736   } else {
737     dwTemp = 0;
738     while ((uint32_t)(1 << dwTemp) < pTRD->SBNUMSYMS) {
739       ++dwTemp;
740     }
741     pTRD->SBSYMCODELEN = (uint8_t)dwTemp;
742   }
743 
744   std::unique_ptr<CJBig2_HuffmanTable> Table_B1;
745   std::unique_ptr<CJBig2_HuffmanTable> Table_B6;
746   std::unique_ptr<CJBig2_HuffmanTable> Table_B7;
747   std::unique_ptr<CJBig2_HuffmanTable> Table_B8;
748   std::unique_ptr<CJBig2_HuffmanTable> Table_B9;
749   std::unique_ptr<CJBig2_HuffmanTable> Table_B10;
750   std::unique_ptr<CJBig2_HuffmanTable> Table_B11;
751   std::unique_ptr<CJBig2_HuffmanTable> Table_B12;
752   std::unique_ptr<CJBig2_HuffmanTable> Table_B13;
753   std::unique_ptr<CJBig2_HuffmanTable> Table_B14;
754   std::unique_ptr<CJBig2_HuffmanTable> Table_B15;
755   if (pTRD->SBHUFF == 1) {
756     if (cSBHUFFFS == 2 || cSBHUFFRDW == 2 || cSBHUFFRDH == 2 ||
757         cSBHUFFRDX == 2 || cSBHUFFRDY == 2) {
758       return JBIG2_ERROR_FATAL;
759     }
760     int32_t nIndex = 0;
761     if (cSBHUFFFS == 0) {
762       Table_B6 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
763           HuffmanTable_B6, HuffmanTable_B6_Size, HuffmanTable_HTOOB_B6);
764       pTRD->SBHUFFFS = Table_B6.get();
765     } else if (cSBHUFFFS == 1) {
766       Table_B7 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
767           HuffmanTable_B7, HuffmanTable_B7_Size, HuffmanTable_HTOOB_B7);
768       pTRD->SBHUFFFS = Table_B7.get();
769     } else {
770       CJBig2_Segment* pSeg =
771           findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
772       if (!pSeg)
773         return JBIG2_ERROR_FATAL;
774       pTRD->SBHUFFFS = pSeg->m_Result.ht;
775     }
776     if (cSBHUFFDS == 0) {
777       Table_B8 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
778           HuffmanTable_B8, HuffmanTable_B8_Size, HuffmanTable_HTOOB_B8);
779       pTRD->SBHUFFDS = Table_B8.get();
780     } else if (cSBHUFFDS == 1) {
781       Table_B9 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
782           HuffmanTable_B9, HuffmanTable_B9_Size, HuffmanTable_HTOOB_B9);
783       pTRD->SBHUFFDS = Table_B9.get();
784     } else if (cSBHUFFDS == 2) {
785       Table_B10 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
786           HuffmanTable_B10, HuffmanTable_B10_Size, HuffmanTable_HTOOB_B10);
787       pTRD->SBHUFFDS = Table_B10.get();
788     } else {
789       CJBig2_Segment* pSeg =
790           findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
791       if (!pSeg)
792         return JBIG2_ERROR_FATAL;
793       pTRD->SBHUFFDS = pSeg->m_Result.ht;
794     }
795     if (cSBHUFFDT == 0) {
796       Table_B11 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
797           HuffmanTable_B11, HuffmanTable_B11_Size, HuffmanTable_HTOOB_B11);
798       pTRD->SBHUFFDT = Table_B11.get();
799     } else if (cSBHUFFDT == 1) {
800       Table_B12 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
801           HuffmanTable_B12, HuffmanTable_B12_Size, HuffmanTable_HTOOB_B12);
802       pTRD->SBHUFFDT = Table_B12.get();
803     } else if (cSBHUFFDT == 2) {
804       Table_B13 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
805           HuffmanTable_B13, HuffmanTable_B13_Size, HuffmanTable_HTOOB_B13);
806       pTRD->SBHUFFDT = Table_B13.get();
807     } else {
808       CJBig2_Segment* pSeg =
809           findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
810       if (!pSeg)
811         return JBIG2_ERROR_FATAL;
812       pTRD->SBHUFFDT = pSeg->m_Result.ht;
813     }
814     if (cSBHUFFRDW == 0) {
815       Table_B14 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
816           HuffmanTable_B14, HuffmanTable_B14_Size, HuffmanTable_HTOOB_B14);
817       pTRD->SBHUFFRDW = Table_B14.get();
818     } else if (cSBHUFFRDW == 1) {
819       Table_B15 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
820           HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15);
821       pTRD->SBHUFFRDW = Table_B15.get();
822     } else {
823       CJBig2_Segment* pSeg =
824           findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
825       if (!pSeg)
826         return JBIG2_ERROR_FATAL;
827       pTRD->SBHUFFRDW = pSeg->m_Result.ht;
828     }
829     if (cSBHUFFRDH == 0) {
830       if (!Table_B14) {
831         Table_B14 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
832             HuffmanTable_B14, HuffmanTable_B14_Size, HuffmanTable_HTOOB_B14);
833       }
834       pTRD->SBHUFFRDH = Table_B14.get();
835     } else if (cSBHUFFRDH == 1) {
836       if (!Table_B15) {
837         Table_B15 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
838             HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15);
839       }
840       pTRD->SBHUFFRDH = Table_B15.get();
841     } else {
842       CJBig2_Segment* pSeg =
843           findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
844       if (!pSeg)
845         return JBIG2_ERROR_FATAL;
846       pTRD->SBHUFFRDH = pSeg->m_Result.ht;
847     }
848     if (cSBHUFFRDX == 0) {
849       if (!Table_B14) {
850         Table_B14 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
851             HuffmanTable_B14, HuffmanTable_B14_Size, HuffmanTable_HTOOB_B14);
852       }
853       pTRD->SBHUFFRDX = Table_B14.get();
854     } else if (cSBHUFFRDX == 1) {
855       if (!Table_B15) {
856         Table_B15 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
857             HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15);
858       }
859       pTRD->SBHUFFRDX = Table_B15.get();
860     } else {
861       CJBig2_Segment* pSeg =
862           findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
863       if (!pSeg)
864         return JBIG2_ERROR_FATAL;
865       pTRD->SBHUFFRDX = pSeg->m_Result.ht;
866     }
867     if (cSBHUFFRDY == 0) {
868       if (!Table_B14) {
869         Table_B14 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
870             HuffmanTable_B14, HuffmanTable_B14_Size, HuffmanTable_HTOOB_B14);
871       }
872       pTRD->SBHUFFRDY = Table_B14.get();
873     } else if (cSBHUFFRDY == 1) {
874       if (!Table_B15) {
875         Table_B15 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
876             HuffmanTable_B15, HuffmanTable_B15_Size, HuffmanTable_HTOOB_B15);
877       }
878       pTRD->SBHUFFRDY = Table_B15.get();
879     } else {
880       CJBig2_Segment* pSeg =
881           findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
882       if (!pSeg)
883         return JBIG2_ERROR_FATAL;
884       pTRD->SBHUFFRDY = pSeg->m_Result.ht;
885     }
886     if (cSBHUFFRSIZE == 0) {
887       Table_B1 = pdfium::MakeUnique<CJBig2_HuffmanTable>(
888           HuffmanTable_B1, HuffmanTable_B1_Size, HuffmanTable_HTOOB_B1);
889       pTRD->SBHUFFRSIZE = Table_B1.get();
890     } else {
891       CJBig2_Segment* pSeg =
892           findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
893       if (!pSeg)
894         return JBIG2_ERROR_FATAL;
895       pTRD->SBHUFFRSIZE = pSeg->m_Result.ht;
896     }
897   }
898   std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> grContext;
899   if (pTRD->SBREFINE == 1) {
900     const size_t size = GetRefAggContextSize(pTRD->SBRTEMPLATE);
901     grContext.reset(FX_Alloc(JBig2ArithCtx, size));
902     JBIG2_memset(grContext.get(), 0, sizeof(JBig2ArithCtx) * size);
903   }
904   if (pTRD->SBHUFF == 0) {
905     std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
906         new CJBig2_ArithDecoder(m_pStream.get()));
907     pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
908     pSegment->m_Result.im =
909         pTRD->decode_Arith(pArithDecoder.get(), grContext.get(), nullptr);
910     if (!pSegment->m_Result.im)
911       return JBIG2_ERROR_FATAL;
912     m_pStream->alignByte();
913     m_pStream->offset(2);
914   } else {
915     pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
916     pSegment->m_Result.im =
917         pTRD->decode_Huffman(m_pStream.get(), grContext.get());
918     if (!pSegment->m_Result.im)
919       return JBIG2_ERROR_FATAL;
920     m_pStream->alignByte();
921   }
922   if (pSegment->m_cFlags.s.type != 4) {
923     if (!m_bBufSpecified) {
924       const auto& pPageInfo = m_PageInfoList.back();
925       if ((pPageInfo->m_bIsStriped == 1) &&
926           (ri.y + ri.height > m_pPage->height())) {
927         m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
928       }
929     }
930     m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
931                          (JBig2ComposeOp)(ri.flags & 0x03));
932     delete pSegment->m_Result.im;
933     pSegment->m_Result.im = nullptr;
934   }
935   return JBIG2_SUCCESS;
936 }
937 
parsePatternDict(CJBig2_Segment * pSegment,IFX_Pause * pPause)938 int32_t CJBig2_Context::parsePatternDict(CJBig2_Segment* pSegment,
939                                          IFX_Pause* pPause) {
940   uint8_t cFlags;
941   std::unique_ptr<CJBig2_PDDProc> pPDD(new CJBig2_PDDProc);
942   if (m_pStream->read1Byte(&cFlags) != 0 ||
943       m_pStream->read1Byte(&pPDD->HDPW) != 0 ||
944       m_pStream->read1Byte(&pPDD->HDPH) != 0 ||
945       m_pStream->readInteger(&pPDD->GRAYMAX) != 0) {
946     return JBIG2_ERROR_TOO_SHORT;
947   }
948   if (pPDD->GRAYMAX > JBIG2_MAX_PATTERN_INDEX)
949     return JBIG2_ERROR_LIMIT;
950 
951   pPDD->HDMMR = cFlags & 0x01;
952   pPDD->HDTEMPLATE = (cFlags >> 1) & 0x03;
953   pSegment->m_nResultType = JBIG2_PATTERN_DICT_POINTER;
954   if (pPDD->HDMMR == 0) {
955     const size_t size = GetHuffContextSize(pPDD->HDTEMPLATE);
956     std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> gbContext(
957         FX_Alloc(JBig2ArithCtx, size));
958     JBIG2_memset(gbContext.get(), 0, sizeof(JBig2ArithCtx) * size);
959     std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
960         new CJBig2_ArithDecoder(m_pStream.get()));
961     pSegment->m_Result.pd =
962         pPDD->decode_Arith(pArithDecoder.get(), gbContext.get(), pPause);
963     if (!pSegment->m_Result.pd)
964       return JBIG2_ERROR_FATAL;
965 
966     m_pStream->alignByte();
967     m_pStream->offset(2);
968   } else {
969     pSegment->m_Result.pd = pPDD->decode_MMR(m_pStream.get(), pPause);
970     if (!pSegment->m_Result.pd)
971       return JBIG2_ERROR_FATAL;
972     m_pStream->alignByte();
973   }
974   return JBIG2_SUCCESS;
975 }
976 
parseHalftoneRegion(CJBig2_Segment * pSegment,IFX_Pause * pPause)977 int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment,
978                                             IFX_Pause* pPause) {
979   uint8_t cFlags;
980   JBig2RegionInfo ri;
981   std::unique_ptr<CJBig2_HTRDProc> pHRD(new CJBig2_HTRDProc);
982   if (parseRegionInfo(&ri) != JBIG2_SUCCESS ||
983       m_pStream->read1Byte(&cFlags) != 0 ||
984       m_pStream->readInteger(&pHRD->HGW) != 0 ||
985       m_pStream->readInteger(&pHRD->HGH) != 0 ||
986       m_pStream->readInteger((uint32_t*)&pHRD->HGX) != 0 ||
987       m_pStream->readInteger((uint32_t*)&pHRD->HGY) != 0 ||
988       m_pStream->readShortInteger(&pHRD->HRX) != 0 ||
989       m_pStream->readShortInteger(&pHRD->HRY) != 0) {
990     return JBIG2_ERROR_TOO_SHORT;
991   }
992 
993   if (pHRD->HGW == 0 || pHRD->HGH == 0)
994     return JBIG2_ERROR_FATAL;
995 
996   pHRD->HBW = ri.width;
997   pHRD->HBH = ri.height;
998   pHRD->HMMR = cFlags & 0x01;
999   pHRD->HTEMPLATE = (cFlags >> 1) & 0x03;
1000   pHRD->HENABLESKIP = (cFlags >> 3) & 0x01;
1001   pHRD->HCOMBOP = (JBig2ComposeOp)((cFlags >> 4) & 0x07);
1002   pHRD->HDEFPIXEL = (cFlags >> 7) & 0x01;
1003   if (pSegment->m_nReferred_to_segment_count != 1)
1004     return JBIG2_ERROR_FATAL;
1005 
1006   CJBig2_Segment* pSeg =
1007       findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]);
1008   if (!pSeg || (pSeg->m_cFlags.s.type != 16))
1009     return JBIG2_ERROR_FATAL;
1010 
1011   CJBig2_PatternDict* pPatternDict = pSeg->m_Result.pd;
1012   if (!pPatternDict || (pPatternDict->NUMPATS == 0))
1013     return JBIG2_ERROR_FATAL;
1014 
1015   pHRD->HNUMPATS = pPatternDict->NUMPATS;
1016   pHRD->HPATS = pPatternDict->HDPATS;
1017   pHRD->HPW = pPatternDict->HDPATS[0]->width();
1018   pHRD->HPH = pPatternDict->HDPATS[0]->height();
1019   pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1020   if (pHRD->HMMR == 0) {
1021     const size_t size = GetHuffContextSize(pHRD->HTEMPLATE);
1022     std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> gbContext(
1023         FX_Alloc(JBig2ArithCtx, size));
1024     JBIG2_memset(gbContext.get(), 0, sizeof(JBig2ArithCtx) * size);
1025     std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
1026         new CJBig2_ArithDecoder(m_pStream.get()));
1027     pSegment->m_Result.im =
1028         pHRD->decode_Arith(pArithDecoder.get(), gbContext.get(), pPause);
1029     if (!pSegment->m_Result.im)
1030       return JBIG2_ERROR_FATAL;
1031 
1032     m_pStream->alignByte();
1033     m_pStream->offset(2);
1034   } else {
1035     pSegment->m_Result.im = pHRD->decode_MMR(m_pStream.get(), pPause);
1036     if (!pSegment->m_Result.im)
1037       return JBIG2_ERROR_FATAL;
1038     m_pStream->alignByte();
1039   }
1040   if (pSegment->m_cFlags.s.type != 20) {
1041     if (!m_bBufSpecified) {
1042       const auto& pPageInfo = m_PageInfoList.back();
1043       if (pPageInfo->m_bIsStriped == 1 &&
1044           ri.y + ri.height > m_pPage->height()) {
1045         m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1046       }
1047     }
1048     m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
1049                          (JBig2ComposeOp)(ri.flags & 0x03));
1050     delete pSegment->m_Result.im;
1051     pSegment->m_Result.im = nullptr;
1052   }
1053   return JBIG2_SUCCESS;
1054 }
1055 
parseGenericRegion(CJBig2_Segment * pSegment,IFX_Pause * pPause)1056 int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment,
1057                                            IFX_Pause* pPause) {
1058   if (!m_pGRD) {
1059     std::unique_ptr<CJBig2_GRDProc> pGRD(new CJBig2_GRDProc);
1060     uint8_t cFlags;
1061     if (parseRegionInfo(&m_ri) != JBIG2_SUCCESS ||
1062         m_pStream->read1Byte(&cFlags) != 0) {
1063       return JBIG2_ERROR_TOO_SHORT;
1064     }
1065     if (m_ri.height < 0 || m_ri.width < 0)
1066       return JBIG2_FAILED;
1067 
1068     pGRD->GBW = m_ri.width;
1069     pGRD->GBH = m_ri.height;
1070     pGRD->MMR = cFlags & 0x01;
1071     pGRD->GBTEMPLATE = (cFlags >> 1) & 0x03;
1072     pGRD->TPGDON = (cFlags >> 3) & 0x01;
1073     if (pGRD->MMR == 0) {
1074       if (pGRD->GBTEMPLATE == 0) {
1075         for (int32_t i = 0; i < 8; ++i) {
1076           if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0) {
1077             return JBIG2_ERROR_TOO_SHORT;
1078           }
1079         }
1080       } else {
1081         for (int32_t i = 0; i < 2; ++i) {
1082           if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0) {
1083             return JBIG2_ERROR_TOO_SHORT;
1084           }
1085         }
1086       }
1087     }
1088     pGRD->USESKIP = 0;
1089     m_pGRD = std::move(pGRD);
1090   }
1091   pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1092   if (m_pGRD->MMR == 0) {
1093     if (m_gbContext.empty()) {
1094       const size_t size = GetHuffContextSize(m_pGRD->GBTEMPLATE);
1095       m_gbContext.resize(size);
1096     }
1097     if (!m_pArithDecoder) {
1098       m_pArithDecoder =
1099           pdfium::MakeUnique<CJBig2_ArithDecoder>(m_pStream.get());
1100       m_ProcessingStatus = m_pGRD->Start_decode_Arith(&pSegment->m_Result.im,
1101                                                       m_pArithDecoder.get(),
1102                                                       &m_gbContext[0], pPause);
1103     } else {
1104       m_ProcessingStatus = m_pGRD->Continue_decode(pPause);
1105     }
1106     if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
1107       if (pSegment->m_cFlags.s.type != 36) {
1108         if (!m_bBufSpecified) {
1109           const auto& pPageInfo = m_PageInfoList.back();
1110           if ((pPageInfo->m_bIsStriped == 1) &&
1111               (m_ri.y + m_ri.height > m_pPage->height())) {
1112             m_pPage->expand(m_ri.y + m_ri.height,
1113                             (pPageInfo->m_cFlags & 4) ? 1 : 0);
1114           }
1115         }
1116         FX_RECT Rect = m_pGRD->GetReplaceRect();
1117         m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top,
1118                              pSegment->m_Result.im,
1119                              (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect);
1120       }
1121       return JBIG2_SUCCESS;
1122     } else {
1123       m_pArithDecoder.reset();
1124       m_gbContext.clear();
1125       if (!pSegment->m_Result.im) {
1126         m_ProcessingStatus = FXCODEC_STATUS_ERROR;
1127         m_pGRD.reset();
1128         return JBIG2_ERROR_FATAL;
1129       }
1130       m_pStream->alignByte();
1131       m_pStream->offset(2);
1132     }
1133   } else {
1134     m_pGRD->Start_decode_MMR(&pSegment->m_Result.im, m_pStream.get(), pPause);
1135     if (!pSegment->m_Result.im) {
1136       m_pGRD.reset();
1137       return JBIG2_ERROR_FATAL;
1138     }
1139     m_pStream->alignByte();
1140   }
1141   if (pSegment->m_cFlags.s.type != 36) {
1142     if (!m_bBufSpecified) {
1143       JBig2PageInfo* pPageInfo = m_PageInfoList.back().get();
1144       if ((pPageInfo->m_bIsStriped == 1) &&
1145           (m_ri.y + m_ri.height > m_pPage->height())) {
1146         m_pPage->expand(m_ri.y + m_ri.height,
1147                         (pPageInfo->m_cFlags & 4) ? 1 : 0);
1148       }
1149     }
1150     FX_RECT Rect = m_pGRD->GetReplaceRect();
1151     m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top,
1152                          pSegment->m_Result.im,
1153                          (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect);
1154     delete pSegment->m_Result.im;
1155     pSegment->m_Result.im = nullptr;
1156   }
1157   m_pGRD.reset();
1158   return JBIG2_SUCCESS;
1159 }
1160 
parseGenericRefinementRegion(CJBig2_Segment * pSegment)1161 int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) {
1162   JBig2RegionInfo ri;
1163   uint8_t cFlags;
1164   if (parseRegionInfo(&ri) != JBIG2_SUCCESS ||
1165       m_pStream->read1Byte(&cFlags) != 0) {
1166     return JBIG2_ERROR_TOO_SHORT;
1167   }
1168   std::unique_ptr<CJBig2_GRRDProc> pGRRD(new CJBig2_GRRDProc);
1169   pGRRD->GRW = ri.width;
1170   pGRRD->GRH = ri.height;
1171   pGRRD->GRTEMPLATE = !!(cFlags & 0x01);
1172   pGRRD->TPGRON = (cFlags >> 1) & 0x01;
1173   if (!pGRRD->GRTEMPLATE) {
1174     for (int32_t i = 0; i < 4; ++i) {
1175       if (m_pStream->read1Byte((uint8_t*)&pGRRD->GRAT[i]) != 0)
1176         return JBIG2_ERROR_TOO_SHORT;
1177     }
1178   }
1179   CJBig2_Segment* pSeg = nullptr;
1180   if (pSegment->m_nReferred_to_segment_count > 0) {
1181     int32_t i;
1182     for (i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
1183       pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]);
1184       if (!pSeg)
1185         return JBIG2_ERROR_FATAL;
1186 
1187       if (pSeg->m_cFlags.s.type == 4 || pSeg->m_cFlags.s.type == 20 ||
1188           pSeg->m_cFlags.s.type == 36 || pSeg->m_cFlags.s.type == 40) {
1189         break;
1190       }
1191     }
1192     if (i >= pSegment->m_nReferred_to_segment_count)
1193       return JBIG2_ERROR_FATAL;
1194 
1195     pGRRD->GRREFERENCE = pSeg->m_Result.im;
1196   } else {
1197     pGRRD->GRREFERENCE = m_pPage.get();
1198   }
1199   pGRRD->GRREFERENCEDX = 0;
1200   pGRRD->GRREFERENCEDY = 0;
1201   const size_t size = GetRefAggContextSize(pGRRD->GRTEMPLATE);
1202   std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> grContext(
1203       FX_Alloc(JBig2ArithCtx, size));
1204   JBIG2_memset(grContext.get(), 0, sizeof(JBig2ArithCtx) * size);
1205   std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
1206       new CJBig2_ArithDecoder(m_pStream.get()));
1207   pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
1208   pSegment->m_Result.im = pGRRD->decode(pArithDecoder.get(), grContext.get());
1209   if (!pSegment->m_Result.im)
1210     return JBIG2_ERROR_FATAL;
1211 
1212   m_pStream->alignByte();
1213   m_pStream->offset(2);
1214   if (pSegment->m_cFlags.s.type != 40) {
1215     if (!m_bBufSpecified) {
1216       JBig2PageInfo* pPageInfo = m_PageInfoList.back().get();
1217       if ((pPageInfo->m_bIsStriped == 1) &&
1218           (ri.y + ri.height > m_pPage->height())) {
1219         m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
1220       }
1221     }
1222     m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
1223                          (JBig2ComposeOp)(ri.flags & 0x03));
1224     delete pSegment->m_Result.im;
1225     pSegment->m_Result.im = nullptr;
1226   }
1227   return JBIG2_SUCCESS;
1228 }
1229 
parseTable(CJBig2_Segment * pSegment)1230 int32_t CJBig2_Context::parseTable(CJBig2_Segment* pSegment) {
1231   pSegment->m_nResultType = JBIG2_HUFFMAN_TABLE_POINTER;
1232   pSegment->m_Result.ht = nullptr;
1233   std::unique_ptr<CJBig2_HuffmanTable> pHuff(
1234       new CJBig2_HuffmanTable(m_pStream.get()));
1235   if (!pHuff->IsOK())
1236     return JBIG2_ERROR_FATAL;
1237 
1238   pSegment->m_Result.ht = pHuff.release();
1239   m_pStream->alignByte();
1240   return JBIG2_SUCCESS;
1241 }
1242 
parseRegionInfo(JBig2RegionInfo * pRI)1243 int32_t CJBig2_Context::parseRegionInfo(JBig2RegionInfo* pRI) {
1244   if (m_pStream->readInteger((uint32_t*)&pRI->width) != 0 ||
1245       m_pStream->readInteger((uint32_t*)&pRI->height) != 0 ||
1246       m_pStream->readInteger((uint32_t*)&pRI->x) != 0 ||
1247       m_pStream->readInteger((uint32_t*)&pRI->y) != 0 ||
1248       m_pStream->read1Byte(&pRI->flags) != 0) {
1249     return JBIG2_ERROR_TOO_SHORT;
1250   }
1251   return JBIG2_SUCCESS;
1252 }
1253 
decodeSymbolIDHuffmanTable(CJBig2_BitStream * pStream,uint32_t SBNUMSYMS)1254 JBig2HuffmanCode* CJBig2_Context::decodeSymbolIDHuffmanTable(
1255     CJBig2_BitStream* pStream,
1256     uint32_t SBNUMSYMS) {
1257   const size_t kRunCodesSize = 35;
1258   int32_t runcodes[kRunCodesSize];
1259   int32_t runcodes_len[kRunCodesSize];
1260   for (size_t i = 0; i < kRunCodesSize; ++i) {
1261     if (pStream->readNBits(4, &runcodes_len[i]) != 0)
1262       return nullptr;
1263   }
1264   huffman_assign_code(runcodes, runcodes_len, kRunCodesSize);
1265 
1266   std::unique_ptr<JBig2HuffmanCode, FxFreeDeleter> SBSYMCODES(
1267       FX_Alloc(JBig2HuffmanCode, SBNUMSYMS));
1268   int32_t run = 0;
1269   int32_t i = 0;
1270   while (i < (int)SBNUMSYMS) {
1271     size_t j;
1272     int32_t nVal = 0;
1273     int32_t nBits = 0;
1274     uint32_t nTemp;
1275     while (true) {
1276       if (pStream->read1Bit(&nTemp) != 0)
1277         return nullptr;
1278 
1279       nVal = (nVal << 1) | nTemp;
1280       ++nBits;
1281       for (j = 0; j < kRunCodesSize; ++j) {
1282         if (nBits == runcodes_len[j] && nVal == runcodes[j])
1283           break;
1284       }
1285       if (j < kRunCodesSize)
1286         break;
1287     }
1288     int32_t runcode = static_cast<int32_t>(j);
1289     if (runcode < 32) {
1290       SBSYMCODES.get()[i].codelen = runcode;
1291       run = 0;
1292     } else if (runcode == 32) {
1293       if (pStream->readNBits(2, &nTemp) != 0)
1294         return nullptr;
1295       run = nTemp + 3;
1296     } else if (runcode == 33) {
1297       if (pStream->readNBits(3, &nTemp) != 0)
1298         return nullptr;
1299       run = nTemp + 3;
1300     } else if (runcode == 34) {
1301       if (pStream->readNBits(7, &nTemp) != 0)
1302         return nullptr;
1303       run = nTemp + 11;
1304     }
1305     if (run > 0) {
1306       if (i + run > (int)SBNUMSYMS)
1307         return nullptr;
1308       for (int32_t k = 0; k < run; ++k) {
1309         if (runcode == 32 && i > 0) {
1310           SBSYMCODES.get()[i + k].codelen = SBSYMCODES.get()[i - 1].codelen;
1311         } else {
1312           SBSYMCODES.get()[i + k].codelen = 0;
1313         }
1314       }
1315       i += run;
1316     } else {
1317       ++i;
1318     }
1319   }
1320   huffman_assign_code(SBSYMCODES.get(), SBNUMSYMS);
1321   return SBSYMCODES.release();
1322 }
1323 
huffman_assign_code(int * CODES,int * PREFLEN,int NTEMP)1324 void CJBig2_Context::huffman_assign_code(int* CODES, int* PREFLEN, int NTEMP) {
1325   // TODO(thestig) CJBig2_HuffmanTable::parseFromCodedBuffer() has similar code.
1326   int CURLEN, LENMAX, CURCODE, CURTEMP, i;
1327   int* LENCOUNT;
1328   int* FIRSTCODE;
1329   LENMAX = 0;
1330   for (i = 0; i < NTEMP; ++i) {
1331     if (PREFLEN[i] > LENMAX) {
1332       LENMAX = PREFLEN[i];
1333     }
1334   }
1335   LENCOUNT = FX_Alloc(int, LENMAX + 1);
1336   JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
1337   FIRSTCODE = FX_Alloc(int, LENMAX + 1);
1338   for (i = 0; i < NTEMP; ++i) {
1339     ++LENCOUNT[PREFLEN[i]];
1340   }
1341   CURLEN = 1;
1342   FIRSTCODE[0] = 0;
1343   LENCOUNT[0] = 0;
1344   while (CURLEN <= LENMAX) {
1345     FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
1346     CURCODE = FIRSTCODE[CURLEN];
1347     CURTEMP = 0;
1348     while (CURTEMP < NTEMP) {
1349       if (PREFLEN[CURTEMP] == CURLEN) {
1350         CODES[CURTEMP] = CURCODE;
1351         CURCODE = CURCODE + 1;
1352       }
1353       CURTEMP = CURTEMP + 1;
1354     }
1355     CURLEN = CURLEN + 1;
1356   }
1357   FX_Free(LENCOUNT);
1358   FX_Free(FIRSTCODE);
1359 }
1360 
huffman_assign_code(JBig2HuffmanCode * SBSYMCODES,int NTEMP)1361 void CJBig2_Context::huffman_assign_code(JBig2HuffmanCode* SBSYMCODES,
1362                                          int NTEMP) {
1363   int CURLEN, LENMAX, CURCODE, CURTEMP, i;
1364   int* LENCOUNT;
1365   int* FIRSTCODE;
1366   LENMAX = 0;
1367   for (i = 0; i < NTEMP; ++i) {
1368     if (SBSYMCODES[i].codelen > LENMAX) {
1369       LENMAX = SBSYMCODES[i].codelen;
1370     }
1371   }
1372   LENCOUNT = FX_Alloc(int, (LENMAX + 1));
1373   JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
1374   FIRSTCODE = FX_Alloc(int, (LENMAX + 1));
1375   for (i = 0; i < NTEMP; ++i) {
1376     ++LENCOUNT[SBSYMCODES[i].codelen];
1377   }
1378   CURLEN = 1;
1379   FIRSTCODE[0] = 0;
1380   LENCOUNT[0] = 0;
1381   while (CURLEN <= LENMAX) {
1382     FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
1383     CURCODE = FIRSTCODE[CURLEN];
1384     CURTEMP = 0;
1385     while (CURTEMP < NTEMP) {
1386       if (SBSYMCODES[CURTEMP].codelen == CURLEN) {
1387         SBSYMCODES[CURTEMP].code = CURCODE;
1388         CURCODE = CURCODE + 1;
1389       }
1390       CURTEMP = CURTEMP + 1;
1391     }
1392     CURLEN = CURLEN + 1;
1393   }
1394   FX_Free(LENCOUNT);
1395   FX_Free(FIRSTCODE);
1396 }
1397