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