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