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