1 // Copyright 2015 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_SddProc.h"
8 
9 #include <string.h>
10 
11 #include <algorithm>
12 #include <memory>
13 #include <utility>
14 #include <vector>
15 
16 #include "core/fxcodec/jbig2/JBig2_ArithIntDecoder.h"
17 #include "core/fxcodec/jbig2/JBig2_GrdProc.h"
18 #include "core/fxcodec/jbig2/JBig2_GrrdProc.h"
19 #include "core/fxcodec/jbig2/JBig2_HuffmanDecoder.h"
20 #include "core/fxcodec/jbig2/JBig2_HuffmanTable.h"
21 #include "core/fxcodec/jbig2/JBig2_SymbolDict.h"
22 #include "core/fxcodec/jbig2/JBig2_TrdProc.h"
23 #include "core/fxcrt/fx_safe_types.h"
24 #include "third_party/base/ptr_util.h"
25 
26 CJBig2_SDDProc::CJBig2_SDDProc() = default;
27 
28 CJBig2_SDDProc::~CJBig2_SDDProc() = default;
29 
DecodeArith(CJBig2_ArithDecoder * pArithDecoder,std::vector<JBig2ArithCtx> * gbContext,std::vector<JBig2ArithCtx> * grContext)30 std::unique_ptr<CJBig2_SymbolDict> CJBig2_SDDProc::DecodeArith(
31     CJBig2_ArithDecoder* pArithDecoder,
32     std::vector<JBig2ArithCtx>* gbContext,
33     std::vector<JBig2ArithCtx>* grContext) {
34   std::vector<std::unique_ptr<CJBig2_Image>> SDNEWSYMS;
35   uint32_t HCHEIGHT, NSYMSDECODED;
36   int32_t HCDH;
37   uint32_t SYMWIDTH, TOTWIDTH;
38   int32_t DW;
39   uint32_t I, J, REFAGGNINST;
40   std::vector<bool> EXFLAGS;
41   uint32_t EXINDEX;
42   bool CUREXFLAG;
43   uint32_t EXRUNLENGTH;
44   uint32_t nTmp;
45   uint32_t SBNUMSYMS;
46   uint8_t SBSYMCODELEN;
47   int32_t RDXI, RDYI;
48   uint32_t num_ex_syms;
49   // Pointers are not owned
50   std::vector<CJBig2_Image*> SBSYMS;
51   std::unique_ptr<CJBig2_ArithIaidDecoder> IAID;
52   std::unique_ptr<CJBig2_SymbolDict> pDict;
53   auto IADH = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
54   auto IADW = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
55   auto IAAI = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
56   auto IARDX = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
57   auto IARDY = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
58   auto IAEX = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
59   auto IADT = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
60   auto IAFS = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
61   auto IADS = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
62   auto IAIT = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
63   auto IARI = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
64   auto IARDW = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
65   auto IARDH = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
66   nTmp = 0;
67   while ((uint32_t)(1 << nTmp) < (SDNUMINSYMS + SDNUMNEWSYMS)) {
68     nTmp++;
69   }
70   IAID = pdfium::MakeUnique<CJBig2_ArithIaidDecoder>((uint8_t)nTmp);
71   SDNEWSYMS.resize(SDNUMNEWSYMS);
72 
73   HCHEIGHT = 0;
74   NSYMSDECODED = 0;
75   while (NSYMSDECODED < SDNUMNEWSYMS) {
76     std::unique_ptr<CJBig2_Image> BS;
77     IADH->Decode(pArithDecoder, &HCDH);
78     HCHEIGHT = HCHEIGHT + HCDH;
79     if ((int)HCHEIGHT < 0 || (int)HCHEIGHT > JBIG2_MAX_IMAGE_SIZE)
80       return nullptr;
81 
82     SYMWIDTH = 0;
83     TOTWIDTH = 0;
84     for (;;) {
85       if (!IADW->Decode(pArithDecoder, &DW))
86         break;
87 
88       if (NSYMSDECODED >= SDNUMNEWSYMS)
89         return nullptr;
90 
91       SYMWIDTH = SYMWIDTH + DW;
92       if ((int)SYMWIDTH < 0 || (int)SYMWIDTH > JBIG2_MAX_IMAGE_SIZE)
93         return nullptr;
94 
95       if (HCHEIGHT == 0 || SYMWIDTH == 0) {
96         TOTWIDTH = TOTWIDTH + SYMWIDTH;
97         SDNEWSYMS[NSYMSDECODED] = nullptr;
98         NSYMSDECODED = NSYMSDECODED + 1;
99         continue;
100       }
101       TOTWIDTH = TOTWIDTH + SYMWIDTH;
102       if (SDREFAGG == 0) {
103         auto pGRD = pdfium::MakeUnique<CJBig2_GRDProc>();
104         pGRD->MMR = 0;
105         pGRD->GBW = SYMWIDTH;
106         pGRD->GBH = HCHEIGHT;
107         pGRD->GBTEMPLATE = SDTEMPLATE;
108         pGRD->TPGDON = 0;
109         pGRD->USESKIP = 0;
110         pGRD->GBAT[0] = SDAT[0];
111         pGRD->GBAT[1] = SDAT[1];
112         pGRD->GBAT[2] = SDAT[2];
113         pGRD->GBAT[3] = SDAT[3];
114         pGRD->GBAT[4] = SDAT[4];
115         pGRD->GBAT[5] = SDAT[5];
116         pGRD->GBAT[6] = SDAT[6];
117         pGRD->GBAT[7] = SDAT[7];
118         BS = pGRD->DecodeArith(pArithDecoder, gbContext->data());
119         if (!BS)
120           return nullptr;
121       } else {
122         IAAI->Decode(pArithDecoder, (int*)&REFAGGNINST);
123         if (REFAGGNINST > 1) {
124           // Huffman tables must not outlive |pDecoder|.
125           auto SBHUFFFS = pdfium::MakeUnique<CJBig2_HuffmanTable>(6);
126           auto SBHUFFDS = pdfium::MakeUnique<CJBig2_HuffmanTable>(8);
127           auto SBHUFFDT = pdfium::MakeUnique<CJBig2_HuffmanTable>(11);
128           auto SBHUFFRDW = pdfium::MakeUnique<CJBig2_HuffmanTable>(15);
129           auto SBHUFFRDH = pdfium::MakeUnique<CJBig2_HuffmanTable>(15);
130           auto SBHUFFRDX = pdfium::MakeUnique<CJBig2_HuffmanTable>(15);
131           auto SBHUFFRDY = pdfium::MakeUnique<CJBig2_HuffmanTable>(15);
132           auto SBHUFFRSIZE = pdfium::MakeUnique<CJBig2_HuffmanTable>(1);
133           auto pDecoder = pdfium::MakeUnique<CJBig2_TRDProc>();
134           pDecoder->SBHUFF = SDHUFF;
135           pDecoder->SBREFINE = 1;
136           pDecoder->SBW = SYMWIDTH;
137           pDecoder->SBH = HCHEIGHT;
138           pDecoder->SBNUMINSTANCES = REFAGGNINST;
139           pDecoder->SBSTRIPS = 1;
140           pDecoder->SBNUMSYMS = SDNUMINSYMS + NSYMSDECODED;
141           SBNUMSYMS = pDecoder->SBNUMSYMS;
142           nTmp = 0;
143           while ((uint32_t)(1 << nTmp) < SBNUMSYMS) {
144             nTmp++;
145           }
146           SBSYMCODELEN = (uint8_t)nTmp;
147           pDecoder->SBSYMCODELEN = SBSYMCODELEN;
148           SBSYMS.resize(SBNUMSYMS);
149           std::copy(SDINSYMS, SDINSYMS + SDNUMINSYMS, SBSYMS.begin());
150           for (size_t i = 0; i < NSYMSDECODED; ++i)
151             SBSYMS[i + SDNUMINSYMS] = SDNEWSYMS[i].get();
152           pDecoder->SBSYMS = SBSYMS.data();
153           pDecoder->SBDEFPIXEL = 0;
154           pDecoder->SBCOMBOP = JBIG2_COMPOSE_OR;
155           pDecoder->TRANSPOSED = 0;
156           pDecoder->REFCORNER = JBIG2_CORNER_TOPLEFT;
157           pDecoder->SBDSOFFSET = 0;
158           pDecoder->SBHUFFFS = SBHUFFFS.get();
159           pDecoder->SBHUFFDS = SBHUFFDS.get();
160           pDecoder->SBHUFFDT = SBHUFFDT.get();
161           pDecoder->SBHUFFRDW = SBHUFFRDW.get();
162           pDecoder->SBHUFFRDH = SBHUFFRDH.get();
163           pDecoder->SBHUFFRDX = SBHUFFRDX.get();
164           pDecoder->SBHUFFRDY = SBHUFFRDY.get();
165           pDecoder->SBHUFFRSIZE = SBHUFFRSIZE.get();
166           pDecoder->SBRTEMPLATE = SDRTEMPLATE;
167           pDecoder->SBRAT[0] = SDRAT[0];
168           pDecoder->SBRAT[1] = SDRAT[1];
169           pDecoder->SBRAT[2] = SDRAT[2];
170           pDecoder->SBRAT[3] = SDRAT[3];
171           JBig2IntDecoderState ids;
172           ids.IADT = IADT.get();
173           ids.IAFS = IAFS.get();
174           ids.IADS = IADS.get();
175           ids.IAIT = IAIT.get();
176           ids.IARI = IARI.get();
177           ids.IARDW = IARDW.get();
178           ids.IARDH = IARDH.get();
179           ids.IARDX = IARDX.get();
180           ids.IARDY = IARDY.get();
181           ids.IAID = IAID.get();
182           BS = pDecoder->DecodeArith(pArithDecoder, grContext->data(), &ids);
183           if (!BS)
184             return nullptr;
185         } else if (REFAGGNINST == 1) {
186           SBNUMSYMS = SDNUMINSYMS + NSYMSDECODED;
187           uint32_t IDI;
188           IAID->Decode(pArithDecoder, &IDI);
189           IARDX->Decode(pArithDecoder, &RDXI);
190           IARDY->Decode(pArithDecoder, &RDYI);
191           if (IDI >= SBNUMSYMS)
192             return nullptr;
193 
194           SBSYMS.resize(SBNUMSYMS);
195           std::copy(SDINSYMS, SDINSYMS + SDNUMINSYMS, SBSYMS.begin());
196           for (size_t i = 0; i < NSYMSDECODED; ++i)
197             SBSYMS[i + SDNUMINSYMS] = SDNEWSYMS[i].get();
198           if (!SBSYMS[IDI])
199             return nullptr;
200 
201           auto pGRRD = pdfium::MakeUnique<CJBig2_GRRDProc>();
202           pGRRD->GRW = SYMWIDTH;
203           pGRRD->GRH = HCHEIGHT;
204           pGRRD->GRTEMPLATE = SDRTEMPLATE;
205           pGRRD->GRREFERENCE = SBSYMS[IDI];
206           pGRRD->GRREFERENCEDX = RDXI;
207           pGRRD->GRREFERENCEDY = RDYI;
208           pGRRD->TPGRON = 0;
209           pGRRD->GRAT[0] = SDRAT[0];
210           pGRRD->GRAT[1] = SDRAT[1];
211           pGRRD->GRAT[2] = SDRAT[2];
212           pGRRD->GRAT[3] = SDRAT[3];
213           BS = pGRRD->Decode(pArithDecoder, grContext->data());
214           if (!BS)
215             return nullptr;
216         }
217       }
218       SDNEWSYMS[NSYMSDECODED] = std::move(BS);
219       NSYMSDECODED = NSYMSDECODED + 1;
220     }
221   }
222   EXINDEX = 0;
223   CUREXFLAG = 0;
224   EXFLAGS.resize(SDNUMINSYMS + SDNUMNEWSYMS);
225   num_ex_syms = 0;
226   while (EXINDEX < SDNUMINSYMS + SDNUMNEWSYMS) {
227     IAEX->Decode(pArithDecoder, (int*)&EXRUNLENGTH);
228     if (EXINDEX + EXRUNLENGTH > SDNUMINSYMS + SDNUMNEWSYMS)
229       return nullptr;
230 
231     if (EXRUNLENGTH != 0) {
232       for (I = EXINDEX; I < EXINDEX + EXRUNLENGTH; I++) {
233         if (CUREXFLAG)
234           num_ex_syms++;
235         EXFLAGS[I] = CUREXFLAG;
236       }
237     }
238     EXINDEX = EXINDEX + EXRUNLENGTH;
239     CUREXFLAG = !CUREXFLAG;
240   }
241   if (num_ex_syms > SDNUMEXSYMS)
242     return nullptr;
243 
244   pDict = pdfium::MakeUnique<CJBig2_SymbolDict>();
245   J = 0;
246   for (I = 0; I < SDNUMINSYMS + SDNUMNEWSYMS; I++) {
247     if (!EXFLAGS[I] || J >= SDNUMEXSYMS)
248       continue;
249     if (I < SDNUMINSYMS) {
250       pDict->AddImage(SDINSYMS[I]
251                           ? pdfium::MakeUnique<CJBig2_Image>(*SDINSYMS[I])
252                           : nullptr);
253     } else {
254       pDict->AddImage(std::move(SDNEWSYMS[I - SDNUMINSYMS]));
255     }
256     ++J;
257   }
258   return pDict;
259 }
260 
DecodeHuffman(CJBig2_BitStream * pStream,std::vector<JBig2ArithCtx> * gbContext,std::vector<JBig2ArithCtx> * grContext)261 std::unique_ptr<CJBig2_SymbolDict> CJBig2_SDDProc::DecodeHuffman(
262     CJBig2_BitStream* pStream,
263     std::vector<JBig2ArithCtx>* gbContext,
264     std::vector<JBig2ArithCtx>* grContext) {
265   std::vector<std::unique_ptr<CJBig2_Image>> SDNEWSYMS;
266   std::vector<uint32_t> SDNEWSYMWIDTHS;
267   uint32_t HCHEIGHT, NSYMSDECODED;
268   int32_t HCDH;
269   uint32_t SYMWIDTH, TOTWIDTH, HCFIRSTSYM;
270   int32_t DW;
271   uint32_t I, J, REFAGGNINST;
272   std::vector<bool> EXFLAGS;
273   uint32_t EXINDEX;
274   bool CUREXFLAG;
275   uint32_t EXRUNLENGTH;
276   int32_t nVal;
277   uint32_t nTmp;
278   uint32_t SBNUMSYMS;
279   uint8_t SBSYMCODELEN;
280   uint32_t IDI;
281   int32_t RDXI, RDYI;
282   uint32_t BMSIZE;
283   uint32_t num_ex_syms;
284   // Pointers are not owned
285   std::vector<CJBig2_Image*> SBSYMS;
286   auto pHuffmanDecoder = pdfium::MakeUnique<CJBig2_HuffmanDecoder>(pStream);
287   SDNEWSYMS.resize(SDNUMNEWSYMS);
288   if (SDREFAGG == 0)
289     SDNEWSYMWIDTHS.resize(SDNUMNEWSYMS);
290   auto pDict = pdfium::MakeUnique<CJBig2_SymbolDict>();
291   std::unique_ptr<CJBig2_HuffmanTable> pTable;
292 
293   HCHEIGHT = 0;
294   NSYMSDECODED = 0;
295   std::unique_ptr<CJBig2_Image> BS;
296   while (NSYMSDECODED < SDNUMNEWSYMS) {
297     if (pHuffmanDecoder->DecodeAValue(SDHUFFDH.Get(), &HCDH) != 0)
298       return nullptr;
299 
300     HCHEIGHT = HCHEIGHT + HCDH;
301     if ((int)HCHEIGHT < 0 || (int)HCHEIGHT > JBIG2_MAX_IMAGE_SIZE)
302       return nullptr;
303 
304     SYMWIDTH = 0;
305     TOTWIDTH = 0;
306     HCFIRSTSYM = NSYMSDECODED;
307     for (;;) {
308       nVal = pHuffmanDecoder->DecodeAValue(SDHUFFDW.Get(), &DW);
309       if (nVal == JBIG2_OOB)
310         break;
311       if (nVal != 0)
312         return nullptr;
313       if (NSYMSDECODED >= SDNUMNEWSYMS)
314         return nullptr;
315 
316       SYMWIDTH = SYMWIDTH + DW;
317       if ((int)SYMWIDTH < 0 || (int)SYMWIDTH > JBIG2_MAX_IMAGE_SIZE)
318         return nullptr;
319       if (HCHEIGHT == 0 || SYMWIDTH == 0) {
320         TOTWIDTH = TOTWIDTH + SYMWIDTH;
321         SDNEWSYMS[NSYMSDECODED] = nullptr;
322         NSYMSDECODED = NSYMSDECODED + 1;
323         continue;
324       }
325       TOTWIDTH = TOTWIDTH + SYMWIDTH;
326       if (SDREFAGG == 1) {
327         if (pHuffmanDecoder->DecodeAValue(SDHUFFAGGINST.Get(),
328                                           (int*)&REFAGGNINST) != 0) {
329           return nullptr;
330         }
331         BS = nullptr;
332         if (REFAGGNINST > 1) {
333           // Huffman tables must outlive |pDecoder|.
334           auto SBHUFFFS = pdfium::MakeUnique<CJBig2_HuffmanTable>(6);
335           auto SBHUFFDS = pdfium::MakeUnique<CJBig2_HuffmanTable>(8);
336           auto SBHUFFDT = pdfium::MakeUnique<CJBig2_HuffmanTable>(11);
337           auto SBHUFFRDW = pdfium::MakeUnique<CJBig2_HuffmanTable>(15);
338           auto SBHUFFRDH = pdfium::MakeUnique<CJBig2_HuffmanTable>(15);
339           auto SBHUFFRDX = pdfium::MakeUnique<CJBig2_HuffmanTable>(15);
340           auto SBHUFFRDY = pdfium::MakeUnique<CJBig2_HuffmanTable>(15);
341           auto SBHUFFRSIZE = pdfium::MakeUnique<CJBig2_HuffmanTable>(1);
342           auto pDecoder = pdfium::MakeUnique<CJBig2_TRDProc>();
343           pDecoder->SBHUFF = SDHUFF;
344           pDecoder->SBREFINE = 1;
345           pDecoder->SBW = SYMWIDTH;
346           pDecoder->SBH = HCHEIGHT;
347           pDecoder->SBNUMINSTANCES = REFAGGNINST;
348           pDecoder->SBSTRIPS = 1;
349           pDecoder->SBNUMSYMS = SDNUMINSYMS + NSYMSDECODED;
350           SBNUMSYMS = pDecoder->SBNUMSYMS;
351           std::vector<JBig2HuffmanCode> SBSYMCODES(SBNUMSYMS);
352           nTmp = 1;
353           while (static_cast<uint32_t>(1 << nTmp) < SBNUMSYMS)
354             ++nTmp;
355           for (I = 0; I < SBNUMSYMS; ++I) {
356             SBSYMCODES[I].codelen = nTmp;
357             SBSYMCODES[I].code = I;
358           }
359           pDecoder->SBSYMCODES = std::move(SBSYMCODES);
360           SBSYMS.resize(SBNUMSYMS);
361           std::copy(SDINSYMS, SDINSYMS + SDNUMINSYMS, SBSYMS.begin());
362           for (size_t i = 0; i < NSYMSDECODED; ++i)
363             SBSYMS[i + SDNUMINSYMS] = SDNEWSYMS[i].get();
364           pDecoder->SBSYMS = SBSYMS.data();
365           pDecoder->SBDEFPIXEL = 0;
366           pDecoder->SBCOMBOP = JBIG2_COMPOSE_OR;
367           pDecoder->TRANSPOSED = 0;
368           pDecoder->REFCORNER = JBIG2_CORNER_TOPLEFT;
369           pDecoder->SBDSOFFSET = 0;
370           pDecoder->SBHUFFFS = SBHUFFFS.get();
371           pDecoder->SBHUFFDS = SBHUFFDS.get();
372           pDecoder->SBHUFFDT = SBHUFFDT.get();
373           pDecoder->SBHUFFRDW = SBHUFFRDW.get();
374           pDecoder->SBHUFFRDH = SBHUFFRDH.get();
375           pDecoder->SBHUFFRDX = SBHUFFRDX.get();
376           pDecoder->SBHUFFRDY = SBHUFFRDY.get();
377           pDecoder->SBHUFFRSIZE = SBHUFFRSIZE.get();
378           pDecoder->SBRTEMPLATE = SDRTEMPLATE;
379           pDecoder->SBRAT[0] = SDRAT[0];
380           pDecoder->SBRAT[1] = SDRAT[1];
381           pDecoder->SBRAT[2] = SDRAT[2];
382           pDecoder->SBRAT[3] = SDRAT[3];
383           BS = pDecoder->DecodeHuffman(pStream, grContext->data());
384           if (!BS)
385             return nullptr;
386 
387         } else if (REFAGGNINST == 1) {
388           SBNUMSYMS = SDNUMINSYMS + SDNUMNEWSYMS;
389           nTmp = 1;
390           while ((uint32_t)(1 << nTmp) < SBNUMSYMS) {
391             nTmp++;
392           }
393           SBSYMCODELEN = (uint8_t)nTmp;
394           uint32_t uVal = 0;
395           for (;;) {
396             if (pStream->read1Bit(&nTmp) != 0)
397               return nullptr;
398 
399             uVal = (uVal << 1) | nTmp;
400             if (uVal >= SBNUMSYMS)
401               return nullptr;
402 
403             IDI = SBSYMCODELEN == 0 ? uVal : SBNUMSYMS;
404             if (IDI < SBNUMSYMS)
405               break;
406           }
407           auto SBHUFFRDX = pdfium::MakeUnique<CJBig2_HuffmanTable>(15);
408           auto SBHUFFRSIZE = pdfium::MakeUnique<CJBig2_HuffmanTable>(1);
409           if ((pHuffmanDecoder->DecodeAValue(SBHUFFRDX.get(), &RDXI) != 0) ||
410               (pHuffmanDecoder->DecodeAValue(SBHUFFRDX.get(), &RDYI) != 0) ||
411               (pHuffmanDecoder->DecodeAValue(SBHUFFRSIZE.get(), &nVal) != 0)) {
412             return nullptr;
413           }
414           pStream->alignByte();
415           nTmp = pStream->getOffset();
416           SBSYMS.resize(SBNUMSYMS);
417           std::copy(SDINSYMS, SDINSYMS + SDNUMINSYMS, SBSYMS.begin());
418           for (size_t i = 0; i < NSYMSDECODED; ++i)
419             SBSYMS[i + SDNUMINSYMS] = SDNEWSYMS[i].get();
420           auto pGRRD = pdfium::MakeUnique<CJBig2_GRRDProc>();
421           pGRRD->GRW = SYMWIDTH;
422           pGRRD->GRH = HCHEIGHT;
423           pGRRD->GRTEMPLATE = SDRTEMPLATE;
424           pGRRD->GRREFERENCE = SBSYMS[IDI];
425           pGRRD->GRREFERENCEDX = RDXI;
426           pGRRD->GRREFERENCEDY = RDYI;
427           pGRRD->TPGRON = 0;
428           pGRRD->GRAT[0] = SDRAT[0];
429           pGRRD->GRAT[1] = SDRAT[1];
430           pGRRD->GRAT[2] = SDRAT[2];
431           pGRRD->GRAT[3] = SDRAT[3];
432           auto pArithDecoder = pdfium::MakeUnique<CJBig2_ArithDecoder>(pStream);
433           BS = pGRRD->Decode(pArithDecoder.get(), grContext->data());
434           if (!BS)
435             return nullptr;
436 
437           pStream->alignByte();
438           pStream->offset(2);
439           if ((uint32_t)nVal != (pStream->getOffset() - nTmp))
440             return nullptr;
441         }
442         SDNEWSYMS[NSYMSDECODED] = std::move(BS);
443       }
444       if (SDREFAGG == 0)
445         SDNEWSYMWIDTHS[NSYMSDECODED] = SYMWIDTH;
446       NSYMSDECODED = NSYMSDECODED + 1;
447     }
448     if (SDREFAGG == 0) {
449       if (pHuffmanDecoder->DecodeAValue(SDHUFFBMSIZE.Get(),
450                                         (int32_t*)&BMSIZE) != 0) {
451         return nullptr;
452       }
453       pStream->alignByte();
454       std::unique_ptr<CJBig2_Image> BHC;
455       if (BMSIZE == 0) {
456         FX_SAFE_UINT32 safe_stride = TOTWIDTH;
457         safe_stride += 7;
458         safe_stride /= 8;
459         FX_SAFE_UINT32 safe_image_size = safe_stride;
460         safe_image_size *= HCHEIGHT;
461         if (!safe_image_size.IsValid() ||
462             pStream->getByteLeft() < safe_image_size.ValueOrDie()) {
463           return nullptr;
464         }
465 
466         const uint32_t stride = safe_stride.ValueOrDie();
467         BHC = pdfium::MakeUnique<CJBig2_Image>(TOTWIDTH, HCHEIGHT);
468         for (I = 0; I < HCHEIGHT; I++) {
469           memcpy(BHC->data() + I * BHC->stride(), pStream->getPointer(),
470                  stride);
471           pStream->offset(stride);
472         }
473       } else {
474         auto pGRD = pdfium::MakeUnique<CJBig2_GRDProc>();
475         pGRD->MMR = 1;
476         pGRD->GBW = TOTWIDTH;
477         pGRD->GBH = HCHEIGHT;
478         pGRD->StartDecodeMMR(&BHC, pStream);
479         pStream->alignByte();
480       }
481       nTmp = 0;
482       if (!BHC)
483         continue;
484 
485       for (I = HCFIRSTSYM; I < NSYMSDECODED; ++I) {
486         SDNEWSYMS[I] = BHC->SubImage(nTmp, 0, SDNEWSYMWIDTHS[I], HCHEIGHT);
487         nTmp += SDNEWSYMWIDTHS[I];
488       }
489     }
490   }
491   EXINDEX = 0;
492   CUREXFLAG = 0;
493   pTable = pdfium::MakeUnique<CJBig2_HuffmanTable>(1);
494   EXFLAGS.resize(SDNUMINSYMS + SDNUMNEWSYMS);
495   num_ex_syms = 0;
496   while (EXINDEX < SDNUMINSYMS + SDNUMNEWSYMS) {
497     if (pHuffmanDecoder->DecodeAValue(pTable.get(), (int*)&EXRUNLENGTH) != 0)
498       return nullptr;
499 
500     if (EXINDEX + EXRUNLENGTH > SDNUMINSYMS + SDNUMNEWSYMS)
501       return nullptr;
502 
503     if (EXRUNLENGTH != 0) {
504       for (I = EXINDEX; I < EXINDEX + EXRUNLENGTH; ++I) {
505         if (CUREXFLAG)
506           num_ex_syms++;
507 
508         EXFLAGS[I] = CUREXFLAG;
509       }
510     }
511     EXINDEX = EXINDEX + EXRUNLENGTH;
512     CUREXFLAG = !CUREXFLAG;
513   }
514   if (num_ex_syms > SDNUMEXSYMS)
515     return nullptr;
516 
517   J = 0;
518   for (I = 0; I < SDNUMINSYMS + SDNUMNEWSYMS; ++I) {
519     if (!EXFLAGS[I] || J >= SDNUMEXSYMS)
520       continue;
521     if (I < SDNUMINSYMS) {
522       pDict->AddImage(SDINSYMS[I]
523                           ? pdfium::MakeUnique<CJBig2_Image>(*SDINSYMS[I])
524                           : nullptr);
525     } else {
526       pDict->AddImage(std::move(SDNEWSYMS[I - SDNUMINSYMS]));
527     }
528     ++J;
529   }
530   return pDict;
531 }
532