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/fx_safe_types.h"
16 #include "core/fxcrt/maybe_owned.h"
17 #include "third_party/base/optional.h"
18 #include "third_party/base/ptr_util.h"
19
20 namespace {
21
CheckTRDDimension(uint32_t dimension,int32_t delta)22 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 {};
27 return {result.ValueOrDie()};
28 }
29
CheckTRDReferenceDimension(int32_t dimension,uint32_t shift,int32_t offset)30 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 {};
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,JBig2ArithCtx * grContext)50 std::unique_ptr<CJBig2_Image> CJBig2_TRDProc::DecodeHuffman(
51 CJBig2_BitStream* pStream,
52 JBig2ArithCtx* grContext) {
53 auto SBREG = pdfium::MakeUnique<CJBig2_Image>(SBW, SBH);
54 if (!SBREG->data())
55 return nullptr;
56
57 SBREG->Fill(SBDEFPIXEL);
58 int32_t INITIAL_STRIPT;
59 auto pHuffmanDecoder = pdfium::MakeUnique<CJBig2_HuffmanDecoder>(pStream);
60 if (pHuffmanDecoder->DecodeAValue(SBHUFFDT.Get(), &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.Get(), &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.Get(), &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.Get(), &IDS);
90 if (nVal == JBIG2_OOB)
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 = 0;
138 if (SBREFINE != 0 && pStream->read1Bit(&RI) != 0)
139 return nullptr;
140
141 MaybeOwned<CJBig2_Image> IBI;
142 if (RI == 0) {
143 IBI = 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.Get(), &RDWI) != 0) ||
151 (pHuffmanDecoder->DecodeAValue(SBHUFFRDH.Get(), &RDHI) != 0) ||
152 (pHuffmanDecoder->DecodeAValue(SBHUFFRDX.Get(), &RDXI) != 0) ||
153 (pHuffmanDecoder->DecodeAValue(SBHUFFRDY.Get(), &RDYI) != 0) ||
154 (pHuffmanDecoder->DecodeAValue(SBHUFFRSIZE.Get(), &HUFFRSIZE) !=
155 0)) {
156 return nullptr;
157 }
158 pStream->alignByte();
159 uint32_t nTmp = pStream->getOffset();
160 CJBig2_Image* IBOI = SBSYMS[IDI];
161 if (!IBOI)
162 return nullptr;
163
164 Optional<uint32_t> WOI = CheckTRDDimension(IBOI->width(), RDWI);
165 Optional<uint32_t> HOI = CheckTRDDimension(IBOI->height(), RDHI);
166 if (!WOI || !HOI)
167 return nullptr;
168
169 Optional<int32_t> GRREFERENCEDX =
170 CheckTRDReferenceDimension(RDWI, 2, RDXI);
171 Optional<int32_t> GRREFERENCEDY =
172 CheckTRDReferenceDimension(RDHI, 2, RDYI);
173 if (!GRREFERENCEDX || !GRREFERENCEDY)
174 return nullptr;
175
176 auto pGRRD = pdfium::MakeUnique<CJBig2_GRRDProc>();
177 pGRRD->GRW = WOI.value();
178 pGRRD->GRH = HOI.value();
179 pGRRD->GRTEMPLATE = SBRTEMPLATE;
180 pGRRD->GRREFERENCE = IBOI;
181 pGRRD->GRREFERENCEDX = GRREFERENCEDX.value();
182 pGRRD->GRREFERENCEDY = GRREFERENCEDY.value();
183 pGRRD->TPGRON = 0;
184 pGRRD->GRAT[0] = SBRAT[0];
185 pGRRD->GRAT[1] = SBRAT[1];
186 pGRRD->GRAT[2] = SBRAT[2];
187 pGRRD->GRAT[3] = SBRAT[3];
188
189 auto pArithDecoder = pdfium::MakeUnique<CJBig2_ArithDecoder>(pStream);
190 IBI = pGRRD->Decode(pArithDecoder.get(), grContext);
191 if (!IBI)
192 return nullptr;
193
194 pStream->alignByte();
195 pStream->offset(2);
196 if (static_cast<uint32_t>(HUFFRSIZE) != (pStream->getOffset() - nTmp))
197 return nullptr;
198 }
199 if (!IBI)
200 continue;
201
202 uint32_t WI = IBI->width();
203 uint32_t HI = IBI->height();
204 if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPRIGHT) ||
205 (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
206 CURS += WI - 1;
207 } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_BOTTOMLEFT) ||
208 (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
209 CURS += HI - 1;
210 }
211 if (!CURS.IsValid())
212 return nullptr;
213
214 int32_t SI = CURS.ValueOrDie();
215 ComposeData compose = GetComposeData(SI, TI, WI, HI);
216 IBI.Get()->ComposeTo(SBREG.get(), compose.x, compose.y, SBCOMBOP);
217 if (compose.increment)
218 CURS += compose.increment;
219 ++NINSTANCES;
220 }
221 }
222 return SBREG;
223 }
224
DecodeArith(CJBig2_ArithDecoder * pArithDecoder,JBig2ArithCtx * grContext,JBig2IntDecoderState * pIDS)225 std::unique_ptr<CJBig2_Image> CJBig2_TRDProc::DecodeArith(
226 CJBig2_ArithDecoder* pArithDecoder,
227 JBig2ArithCtx* grContext,
228 JBig2IntDecoderState* pIDS) {
229 auto SBREG = pdfium::MakeUnique<CJBig2_Image>(SBW, SBH);
230 if (!SBREG->data())
231 return nullptr;
232
233 MaybeOwned<CJBig2_ArithIntDecoder> pIADT;
234 if (pIDS)
235 pIADT = pIDS->IADT;
236 else
237 pIADT = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
238 int32_t INITIAL_STRIPT;
239 if (!pIADT->Decode(pArithDecoder, &INITIAL_STRIPT))
240 return nullptr;
241
242 MaybeOwned<CJBig2_ArithIntDecoder> pIAFS;
243 MaybeOwned<CJBig2_ArithIntDecoder> pIADS;
244 MaybeOwned<CJBig2_ArithIntDecoder> pIAIT;
245 MaybeOwned<CJBig2_ArithIntDecoder> pIARI;
246 MaybeOwned<CJBig2_ArithIntDecoder> pIARDW;
247 MaybeOwned<CJBig2_ArithIntDecoder> pIARDH;
248 MaybeOwned<CJBig2_ArithIntDecoder> pIARDX;
249 MaybeOwned<CJBig2_ArithIntDecoder> pIARDY;
250 MaybeOwned<CJBig2_ArithIaidDecoder> pIAID;
251 if (pIDS) {
252 pIAFS = pIDS->IAFS;
253 pIADS = pIDS->IADS;
254 pIAIT = pIDS->IAIT;
255 pIARI = pIDS->IARI;
256 pIARDW = pIDS->IARDW;
257 pIARDH = pIDS->IARDH;
258 pIARDX = pIDS->IARDX;
259 pIARDY = pIDS->IARDY;
260 pIAID = pIDS->IAID;
261 } else {
262 pIAFS = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
263 pIADS = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
264 pIAIT = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
265 pIARI = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
266 pIARDW = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
267 pIARDH = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
268 pIARDX = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
269 pIARDY = pdfium::MakeUnique<CJBig2_ArithIntDecoder>();
270 pIAID = pdfium::MakeUnique<CJBig2_ArithIaidDecoder>(SBSYMCODELEN);
271 }
272
273 SBREG->Fill(SBDEFPIXEL);
274
275 FX_SAFE_INT32 STRIPT = INITIAL_STRIPT;
276 STRIPT *= SBSTRIPS;
277 STRIPT = -STRIPT;
278 FX_SAFE_INT32 FIRSTS = 0;
279 uint32_t NINSTANCES = 0;
280 while (NINSTANCES < SBNUMINSTANCES) {
281 FX_SAFE_INT32 CURS = 0;
282 int32_t INITIAL_DT;
283 if (!pIADT->Decode(pArithDecoder, &INITIAL_DT))
284 return nullptr;
285
286 FX_SAFE_INT32 DT = INITIAL_DT;
287 DT *= SBSTRIPS;
288 STRIPT += DT;
289 bool bFirst = true;
290 for (;;) {
291 if (bFirst) {
292 int32_t DFS;
293 pIAFS->Decode(pArithDecoder, &DFS);
294 FIRSTS += DFS;
295 CURS = FIRSTS;
296 bFirst = false;
297 } else {
298 int32_t IDS;
299 if (!pIADS->Decode(pArithDecoder, &IDS))
300 break;
301
302 CURS += IDS;
303 CURS += SBDSOFFSET;
304 }
305 if (NINSTANCES >= SBNUMINSTANCES)
306 break;
307
308 int CURT = 0;
309 if (SBSTRIPS != 1)
310 pIAIT->Decode(pArithDecoder, &CURT);
311
312 FX_SAFE_INT32 SAFE_TI = STRIPT + CURT;
313 if (!SAFE_TI.IsValid())
314 return nullptr;
315
316 int32_t TI = SAFE_TI.ValueOrDie();
317 uint32_t IDI;
318 pIAID->Decode(pArithDecoder, &IDI);
319 if (IDI >= SBNUMSYMS)
320 return nullptr;
321
322 int RI;
323 if (SBREFINE == 0)
324 RI = 0;
325 else
326 pIARI->Decode(pArithDecoder, &RI);
327
328 MaybeOwned<CJBig2_Image> pIBI;
329 if (RI == 0) {
330 pIBI = SBSYMS[IDI];
331 } else {
332 int32_t RDWI;
333 int32_t RDHI;
334 int32_t RDXI;
335 int32_t RDYI;
336 pIARDW->Decode(pArithDecoder, &RDWI);
337 pIARDH->Decode(pArithDecoder, &RDHI);
338 pIARDX->Decode(pArithDecoder, &RDXI);
339 pIARDY->Decode(pArithDecoder, &RDYI);
340 CJBig2_Image* IBOI = SBSYMS[IDI];
341 if (!IBOI)
342 return nullptr;
343
344 Optional<uint32_t> WOI = CheckTRDDimension(IBOI->width(), RDWI);
345 Optional<uint32_t> HOI = CheckTRDDimension(IBOI->height(), RDHI);
346 if (!WOI || !HOI)
347 return nullptr;
348
349 Optional<int32_t> GRREFERENCEDX =
350 CheckTRDReferenceDimension(RDWI, 1, RDXI);
351 Optional<int32_t> GRREFERENCEDY =
352 CheckTRDReferenceDimension(RDHI, 1, RDYI);
353 if (!GRREFERENCEDX || !GRREFERENCEDY)
354 return nullptr;
355
356 auto pGRRD = pdfium::MakeUnique<CJBig2_GRRDProc>();
357 pGRRD->GRW = WOI.value();
358 pGRRD->GRH = HOI.value();
359 pGRRD->GRTEMPLATE = SBRTEMPLATE;
360 pGRRD->GRREFERENCE = IBOI;
361 pGRRD->GRREFERENCEDX = GRREFERENCEDX.value();
362 pGRRD->GRREFERENCEDY = GRREFERENCEDY.value();
363 pGRRD->TPGRON = 0;
364 pGRRD->GRAT[0] = SBRAT[0];
365 pGRRD->GRAT[1] = SBRAT[1];
366 pGRRD->GRAT[2] = SBRAT[2];
367 pGRRD->GRAT[3] = SBRAT[3];
368 pIBI = pGRRD->Decode(pArithDecoder, grContext);
369 }
370 if (!pIBI)
371 return nullptr;
372
373 uint32_t WI = pIBI->width();
374 uint32_t HI = pIBI->height();
375 if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPRIGHT) ||
376 (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
377 CURS += WI - 1;
378 } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_BOTTOMLEFT) ||
379 (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
380 CURS += HI - 1;
381 }
382 if (!CURS.IsValid())
383 return nullptr;
384
385 int32_t SI = CURS.ValueOrDie();
386 ComposeData compose = GetComposeData(SI, TI, WI, HI);
387 pIBI.Get()->ComposeTo(SBREG.get(), compose.x, compose.y, SBCOMBOP);
388 if (compose.increment)
389 CURS += compose.increment;
390 ++NINSTANCES;
391 }
392 }
393 return SBREG;
394 }
395
GetComposeData(int32_t SI,int32_t TI,uint32_t WI,uint32_t HI) const396 CJBig2_TRDProc::ComposeData CJBig2_TRDProc::GetComposeData(int32_t SI,
397 int32_t TI,
398 uint32_t WI,
399 uint32_t HI) const {
400 ComposeData results;
401 if (TRANSPOSED == 0) {
402 switch (REFCORNER) {
403 case JBIG2_CORNER_TOPLEFT:
404 results.x = SI;
405 results.y = TI;
406 results.increment = WI - 1;
407 break;
408 case JBIG2_CORNER_TOPRIGHT:
409 results.x = SI - WI + 1;
410 results.y = TI;
411 break;
412 case JBIG2_CORNER_BOTTOMLEFT:
413 results.x = SI;
414 results.y = TI - HI + 1;
415 results.increment = WI - 1;
416 break;
417 case JBIG2_CORNER_BOTTOMRIGHT:
418 results.x = SI - WI + 1;
419 results.y = TI - HI + 1;
420 break;
421 }
422 } else {
423 switch (REFCORNER) {
424 case JBIG2_CORNER_TOPLEFT:
425 results.x = TI;
426 results.y = SI;
427 results.increment = HI - 1;
428 break;
429 case JBIG2_CORNER_TOPRIGHT:
430 results.x = TI - WI + 1;
431 results.y = SI;
432 results.increment = HI - 1;
433 break;
434 case JBIG2_CORNER_BOTTOMLEFT:
435 results.x = TI;
436 results.y = SI - HI + 1;
437 break;
438 case JBIG2_CORNER_BOTTOMRIGHT:
439 results.x = TI - WI + 1;
440 results.y = SI - HI + 1;
441 break;
442 }
443 }
444 return results;
445 }
446