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