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_TrdProc.h"
8 
9 #include <memory>
10 
11 #include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
12 #include "core/fxcodec/jbig2/JBig2_ArithIntDecoder.h"
13 #include "core/fxcodec/jbig2/JBig2_GrrdProc.h"
14 #include "core/fxcodec/jbig2/JBig2_HuffmanDecoder.h"
15 #include "core/fxcrt/maybe_owned.h"
16 #include "third_party/base/ptr_util.h"
17 
CJBig2_TRDProc()18 CJBig2_TRDProc::CJBig2_TRDProc() {}
19 
~CJBig2_TRDProc()20 CJBig2_TRDProc::~CJBig2_TRDProc() {}
21 
decode_Huffman(CJBig2_BitStream * pStream,JBig2ArithCtx * grContext)22 std::unique_ptr<CJBig2_Image> CJBig2_TRDProc::decode_Huffman(
23     CJBig2_BitStream* pStream,
24     JBig2ArithCtx* grContext) {
25   auto pHuffmanDecoder = pdfium::MakeUnique<CJBig2_HuffmanDecoder>(pStream);
26   auto SBREG = pdfium::MakeUnique<CJBig2_Image>(SBW, SBH);
27   SBREG->fill(SBDEFPIXEL);
28   int32_t INITIAL_STRIPT;
29   if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &INITIAL_STRIPT) != 0)
30     return nullptr;
31 
32   FX_SAFE_INT32 STRIPT = INITIAL_STRIPT;
33   STRIPT *= SBSTRIPS;
34   STRIPT = -STRIPT;
35   FX_SAFE_INT32 FIRSTS = 0;
36   uint32_t NINSTANCES = 0;
37   while (NINSTANCES < SBNUMINSTANCES) {
38     int32_t INITIAL_DT;
39     if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &INITIAL_DT) != 0)
40       return nullptr;
41 
42     FX_SAFE_INT32 DT = INITIAL_DT;
43     DT *= SBSTRIPS;
44     STRIPT += DT;
45     bool bFirst = true;
46     FX_SAFE_INT32 CURS = 0;
47     for (;;) {
48       if (bFirst) {
49         int32_t DFS;
50         if (pHuffmanDecoder->decodeAValue(SBHUFFFS, &DFS) != 0)
51           return nullptr;
52 
53         FIRSTS += DFS;
54         CURS = FIRSTS;
55         bFirst = false;
56       } else {
57         int32_t IDS;
58         int32_t nVal = pHuffmanDecoder->decodeAValue(SBHUFFDS, &IDS);
59         if (nVal == JBIG2_OOB)
60           break;
61 
62         if (nVal != 0)
63           return nullptr;
64 
65         CURS += IDS;
66         CURS += SBDSOFFSET;
67       }
68       uint8_t CURT = 0;
69       if (SBSTRIPS != 1) {
70         uint32_t nTmp = 1;
71         while (static_cast<uint32_t>(1 << nTmp) < SBSTRIPS)
72           ++nTmp;
73         int32_t nVal;
74         if (pStream->readNBits(nTmp, &nVal) != 0)
75           return nullptr;
76 
77         CURT = nVal;
78       }
79       FX_SAFE_INT32 SAFE_TI = STRIPT + CURT;
80       if (!SAFE_TI.IsValid())
81         return nullptr;
82 
83       int32_t TI = SAFE_TI.ValueOrDie();
84       pdfium::base::CheckedNumeric<int32_t> nVal = 0;
85       int32_t nBits = 0;
86       uint32_t IDI;
87       for (;;) {
88         uint32_t nTmp;
89         if (pStream->read1Bit(&nTmp) != 0)
90           return nullptr;
91 
92         nVal <<= 1;
93         if (!nVal.IsValid())
94           return nullptr;
95 
96         nVal |= nTmp;
97         ++nBits;
98         for (IDI = 0; IDI < SBNUMSYMS; ++IDI) {
99           if ((nBits == SBSYMCODES[IDI].codelen) &&
100               (nVal.ValueOrDie() == SBSYMCODES[IDI].code)) {
101             break;
102           }
103         }
104         if (IDI < SBNUMSYMS)
105           break;
106       }
107       bool RI = 0;
108       if (SBREFINE != 0 && pStream->read1Bit(&RI) != 0)
109         return nullptr;
110 
111       MaybeOwned<CJBig2_Image> IBI;
112       if (RI == 0) {
113         IBI = SBSYMS[IDI];
114       } else {
115         int32_t RDWI;
116         int32_t RDHI;
117         int32_t RDXI;
118         int32_t RDYI;
119         int32_t HUFFRSIZE;
120         if ((pHuffmanDecoder->decodeAValue(SBHUFFRDW, &RDWI) != 0) ||
121             (pHuffmanDecoder->decodeAValue(SBHUFFRDH, &RDHI) != 0) ||
122             (pHuffmanDecoder->decodeAValue(SBHUFFRDX, &RDXI) != 0) ||
123             (pHuffmanDecoder->decodeAValue(SBHUFFRDY, &RDYI) != 0) ||
124             (pHuffmanDecoder->decodeAValue(SBHUFFRSIZE, &HUFFRSIZE) != 0)) {
125           return nullptr;
126         }
127         pStream->alignByte();
128         uint32_t nTmp = pStream->getOffset();
129         CJBig2_Image* IBOI = SBSYMS[IDI];
130         if (!IBOI)
131           return nullptr;
132 
133         uint32_t WOI = IBOI->width();
134         uint32_t HOI = IBOI->height();
135         if (static_cast<int>(WOI + RDWI) < 0 ||
136             static_cast<int>(HOI + RDHI) < 0) {
137           return nullptr;
138         }
139 
140         auto pGRRD = pdfium::MakeUnique<CJBig2_GRRDProc>();
141         pGRRD->GRW = WOI + RDWI;
142         pGRRD->GRH = HOI + RDHI;
143         pGRRD->GRTEMPLATE = SBRTEMPLATE;
144         pGRRD->GRREFERENCE = IBOI;
145         pGRRD->GRREFERENCEDX = (RDWI >> 2) + RDXI;
146         pGRRD->GRREFERENCEDY = (RDHI >> 2) + RDYI;
147         pGRRD->TPGRON = 0;
148         pGRRD->GRAT[0] = SBRAT[0];
149         pGRRD->GRAT[1] = SBRAT[1];
150         pGRRD->GRAT[2] = SBRAT[2];
151         pGRRD->GRAT[3] = SBRAT[3];
152 
153         auto pArithDecoder = pdfium::MakeUnique<CJBig2_ArithDecoder>(pStream);
154         IBI = pGRRD->decode(pArithDecoder.get(), grContext);
155         if (!IBI)
156           return nullptr;
157 
158         pStream->alignByte();
159         pStream->offset(2);
160         if (static_cast<uint32_t>(HUFFRSIZE) != (pStream->getOffset() - nTmp))
161           return nullptr;
162       }
163       if (!IBI)
164         continue;
165 
166       uint32_t WI = IBI->width();
167       uint32_t HI = IBI->height();
168       if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPRIGHT) ||
169                               (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
170         CURS += WI - 1;
171       } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_BOTTOMLEFT) ||
172                                      (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
173         CURS += HI - 1;
174       }
175       if (!CURS.IsValid())
176         return nullptr;
177 
178       int32_t SI = CURS.ValueOrDie();
179       if (TRANSPOSED == 0) {
180         switch (REFCORNER) {
181           case JBIG2_CORNER_TOPLEFT:
182             SBREG->composeFrom(SI, TI, IBI.Get(), SBCOMBOP);
183             break;
184           case JBIG2_CORNER_TOPRIGHT:
185             SBREG->composeFrom(SI - WI + 1, TI, IBI.Get(), SBCOMBOP);
186             break;
187           case JBIG2_CORNER_BOTTOMLEFT:
188             SBREG->composeFrom(SI, TI - HI + 1, IBI.Get(), SBCOMBOP);
189             break;
190           case JBIG2_CORNER_BOTTOMRIGHT:
191             SBREG->composeFrom(SI - WI + 1, TI - HI + 1, IBI.Get(), SBCOMBOP);
192             break;
193         }
194       } else {
195         switch (REFCORNER) {
196           case JBIG2_CORNER_TOPLEFT:
197             SBREG->composeFrom(TI, SI, IBI.Get(), SBCOMBOP);
198             break;
199           case JBIG2_CORNER_TOPRIGHT:
200             SBREG->composeFrom(TI - WI + 1, SI, IBI.Get(), SBCOMBOP);
201             break;
202           case JBIG2_CORNER_BOTTOMLEFT:
203             SBREG->composeFrom(TI, SI - HI + 1, IBI.Get(), SBCOMBOP);
204             break;
205           case JBIG2_CORNER_BOTTOMRIGHT:
206             SBREG->composeFrom(TI - WI + 1, SI - HI + 1, IBI.Get(), SBCOMBOP);
207             break;
208         }
209       }
210       if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
211                               (REFCORNER == JBIG2_CORNER_BOTTOMLEFT))) {
212         CURS += WI - 1;
213       } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
214                                      (REFCORNER == JBIG2_CORNER_TOPRIGHT))) {
215         CURS += HI - 1;
216       }
217       NINSTANCES = NINSTANCES + 1;
218     }
219   }
220   return SBREG;
221 }
222 
decode_Arith(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * grContext,JBig2IntDecoderState * pIDS)223 std::unique_ptr<CJBig2_Image> CJBig2_TRDProc::decode_Arith(
224     CJBig2_ArithDecoder* pArithDecoder,
225     JBig2ArithCtx* grContext,
226     JBig2IntDecoderState* pIDS) {
227   MaybeOwned<CJBig2_ArithIntDecoder> pIADT;
228   MaybeOwned<CJBig2_ArithIntDecoder> pIAFS;
229   MaybeOwned<CJBig2_ArithIntDecoder> pIADS;
230   MaybeOwned<CJBig2_ArithIntDecoder> pIAIT;
231   MaybeOwned<CJBig2_ArithIntDecoder> pIARI;
232   MaybeOwned<CJBig2_ArithIntDecoder> pIARDW;
233   MaybeOwned<CJBig2_ArithIntDecoder> pIARDH;
234   MaybeOwned<CJBig2_ArithIntDecoder> pIARDX;
235   MaybeOwned<CJBig2_ArithIntDecoder> pIARDY;
236   MaybeOwned<CJBig2_ArithIaidDecoder> pIAID;
237   if (pIDS) {
238     pIADT = pIDS->IADT;
239     pIAFS = pIDS->IAFS;
240     pIADS = pIDS->IADS;
241     pIAIT = pIDS->IAIT;
242     pIARI = pIDS->IARI;
243     pIARDW = pIDS->IARDW;
244     pIARDH = pIDS->IARDH;
245     pIARDX = pIDS->IARDX;
246     pIARDY = pIDS->IARDY;
247     pIAID = pIDS->IAID;
248   } else {
249     pIADT = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
250     pIAFS = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
251     pIADS = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
252     pIAIT = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
253     pIARI = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
254     pIARDW = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
255     pIARDH = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
256     pIARDX = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
257     pIARDY = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
258     pIAID = pdfium::MakeUnique<CJBig2_ArithIaidDecoder>(SBSYMCODELEN);
259   }
260   auto SBREG = pdfium::MakeUnique<CJBig2_Image>(SBW, SBH);
261   SBREG->fill(SBDEFPIXEL);
262   int32_t INITIAL_STRIPT;
263   if (!pIADT->decode(pArithDecoder, &INITIAL_STRIPT))
264     return nullptr;
265 
266   FX_SAFE_INT32 STRIPT = INITIAL_STRIPT;
267   STRIPT *= SBSTRIPS;
268   STRIPT = -STRIPT;
269   FX_SAFE_INT32 FIRSTS = 0;
270   uint32_t NINSTANCES = 0;
271   while (NINSTANCES < SBNUMINSTANCES) {
272     FX_SAFE_INT32 CURS = 0;
273     int32_t INITIAL_DT;
274     if (!pIADT->decode(pArithDecoder, &INITIAL_DT))
275       return nullptr;
276 
277     FX_SAFE_INT32 DT = INITIAL_DT;
278     DT *= SBSTRIPS;
279     STRIPT += DT;
280     bool bFirst = true;
281     for (;;) {
282       if (bFirst) {
283         int32_t DFS;
284         pIAFS->decode(pArithDecoder, &DFS);
285         FIRSTS += DFS;
286         CURS = FIRSTS;
287         bFirst = false;
288       } else {
289         int32_t IDS;
290         if (!pIADS->decode(pArithDecoder, &IDS))
291           break;
292 
293         CURS += IDS;
294         CURS += SBDSOFFSET;
295       }
296       if (NINSTANCES >= SBNUMINSTANCES)
297         break;
298 
299       int CURT = 0;
300       if (SBSTRIPS != 1)
301         pIAIT->decode(pArithDecoder, &CURT);
302 
303       FX_SAFE_INT32 SAFE_TI = STRIPT + CURT;
304       if (!SAFE_TI.IsValid())
305         return nullptr;
306 
307       int32_t TI = SAFE_TI.ValueOrDie();
308       uint32_t IDI;
309       pIAID->decode(pArithDecoder, &IDI);
310       if (IDI >= SBNUMSYMS)
311         return nullptr;
312 
313       int RI;
314       if (SBREFINE == 0)
315         RI = 0;
316       else
317         pIARI->decode(pArithDecoder, &RI);
318 
319       MaybeOwned<CJBig2_Image> pIBI;
320       if (RI == 0) {
321         pIBI = SBSYMS[IDI];
322       } else {
323         int32_t RDWI;
324         int32_t RDHI;
325         int32_t RDXI;
326         int32_t RDYI;
327         pIARDW->decode(pArithDecoder, &RDWI);
328         pIARDH->decode(pArithDecoder, &RDHI);
329         pIARDX->decode(pArithDecoder, &RDXI);
330         pIARDY->decode(pArithDecoder, &RDYI);
331         CJBig2_Image* IBOI = SBSYMS[IDI];
332         if (!IBOI)
333           return nullptr;
334 
335         uint32_t WOI = IBOI->width();
336         uint32_t HOI = IBOI->height();
337         if (static_cast<int>(WOI + RDWI) < 0 ||
338             static_cast<int>(HOI + RDHI) < 0) {
339           return nullptr;
340         }
341 
342         auto pGRRD = pdfium::MakeUnique<CJBig2_GRRDProc>();
343         pGRRD->GRW = WOI + RDWI;
344         pGRRD->GRH = HOI + RDHI;
345         pGRRD->GRTEMPLATE = SBRTEMPLATE;
346         pGRRD->GRREFERENCE = IBOI;
347         pGRRD->GRREFERENCEDX = (RDWI >> 1) + RDXI;
348         pGRRD->GRREFERENCEDY = (RDHI >> 1) + RDYI;
349         pGRRD->TPGRON = 0;
350         pGRRD->GRAT[0] = SBRAT[0];
351         pGRRD->GRAT[1] = SBRAT[1];
352         pGRRD->GRAT[2] = SBRAT[2];
353         pGRRD->GRAT[3] = SBRAT[3];
354         pIBI = pGRRD->decode(pArithDecoder, grContext);
355       }
356       if (!pIBI)
357         return nullptr;
358 
359       uint32_t WI = pIBI->width();
360       uint32_t HI = pIBI->height();
361       if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPRIGHT) ||
362                               (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
363         CURS += WI - 1;
364       } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_BOTTOMLEFT) ||
365                                      (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
366         CURS += HI - 1;
367       }
368       if (!CURS.IsValid())
369         return nullptr;
370 
371       int32_t SI = CURS.ValueOrDie();
372       if (TRANSPOSED == 0) {
373         switch (REFCORNER) {
374           case JBIG2_CORNER_TOPLEFT:
375             SBREG->composeFrom(SI, TI, pIBI.Get(), SBCOMBOP);
376             break;
377           case JBIG2_CORNER_TOPRIGHT:
378             SBREG->composeFrom(SI - WI + 1, TI, pIBI.Get(), SBCOMBOP);
379             break;
380           case JBIG2_CORNER_BOTTOMLEFT:
381             SBREG->composeFrom(SI, TI - HI + 1, pIBI.Get(), SBCOMBOP);
382             break;
383           case JBIG2_CORNER_BOTTOMRIGHT:
384             SBREG->composeFrom(SI - WI + 1, TI - HI + 1, pIBI.Get(), SBCOMBOP);
385             break;
386         }
387       } else {
388         switch (REFCORNER) {
389           case JBIG2_CORNER_TOPLEFT:
390             SBREG->composeFrom(TI, SI, pIBI.Get(), SBCOMBOP);
391             break;
392           case JBIG2_CORNER_TOPRIGHT:
393             SBREG->composeFrom(TI - WI + 1, SI, pIBI.Get(), SBCOMBOP);
394             break;
395           case JBIG2_CORNER_BOTTOMLEFT:
396             SBREG->composeFrom(TI, SI - HI + 1, pIBI.Get(), SBCOMBOP);
397             break;
398           case JBIG2_CORNER_BOTTOMRIGHT:
399             SBREG->composeFrom(TI - WI + 1, SI - HI + 1, pIBI.Get(), SBCOMBOP);
400             break;
401         }
402       }
403       if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
404                               (REFCORNER == JBIG2_CORNER_BOTTOMLEFT))) {
405         CURS += WI - 1;
406       } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
407                                      (REFCORNER == JBIG2_CORNER_TOPRIGHT))) {
408         CURS += HI - 1;
409       }
410       ++NINSTANCES;
411     }
412   }
413   return SBREG;
414 }
415