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