1 // Copyright 2014 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/codec/codec_int.h"
8
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 #include <vector>
13
14 #include "core/fxcodec/codec/ccodec_flatemodule.h"
15 #include "core/fxcodec/codec/ccodec_scanlinedecoder.h"
16 #include "core/fxcrt/fx_extension.h"
17 #include "third_party/base/numerics/safe_conversions.h"
18 #include "third_party/base/ptr_util.h"
19
20 #if defined(USE_SYSTEM_ZLIB)
21 #include <zlib.h>
22 #else
23 #include "third_party/zlib/zlib.h"
24 #endif
25
26 extern "C" {
27
my_alloc_func(void * opaque,unsigned int items,unsigned int size)28 static void* my_alloc_func(void* opaque,
29 unsigned int items,
30 unsigned int size) {
31 return FX_Alloc2D(uint8_t, items, size);
32 }
33
my_free_func(void * opaque,void * address)34 static void my_free_func(void* opaque, void* address) {
35 FX_Free(address);
36 }
37
38 } // extern "C"
39
40 namespace {
41
FlateGetPossiblyTruncatedTotalOut(void * context)42 uint32_t FlateGetPossiblyTruncatedTotalOut(void* context) {
43 return pdfium::base::saturated_cast<uint32_t>(
44 static_cast<z_stream*>(context)->total_out);
45 }
46
FlateGetPossiblyTruncatedTotalIn(void * context)47 uint32_t FlateGetPossiblyTruncatedTotalIn(void* context) {
48 return pdfium::base::saturated_cast<uint32_t>(
49 static_cast<z_stream*>(context)->total_in);
50 }
51
FlateCompress(unsigned char * dest_buf,unsigned long * dest_size,const unsigned char * src_buf,uint32_t src_size)52 bool FlateCompress(unsigned char* dest_buf,
53 unsigned long* dest_size,
54 const unsigned char* src_buf,
55 uint32_t src_size) {
56 return compress(dest_buf, dest_size, src_buf, src_size) == Z_OK;
57 }
58
FlateInit()59 void* FlateInit() {
60 z_stream* p = FX_Alloc(z_stream, 1);
61 memset(p, 0, sizeof(z_stream));
62 p->zalloc = my_alloc_func;
63 p->zfree = my_free_func;
64 inflateInit(p);
65 return p;
66 }
67
FlateInput(void * context,const unsigned char * src_buf,uint32_t src_size)68 void FlateInput(void* context,
69 const unsigned char* src_buf,
70 uint32_t src_size) {
71 static_cast<z_stream*>(context)->next_in =
72 const_cast<unsigned char*>(src_buf);
73 static_cast<z_stream*>(context)->avail_in = src_size;
74 }
75
FlateOutput(void * context,unsigned char * dest_buf,uint32_t dest_size)76 uint32_t FlateOutput(void* context,
77 unsigned char* dest_buf,
78 uint32_t dest_size) {
79 static_cast<z_stream*>(context)->next_out = dest_buf;
80 static_cast<z_stream*>(context)->avail_out = dest_size;
81 uint32_t pre_pos = FlateGetPossiblyTruncatedTotalOut(context);
82 int ret = inflate(static_cast<z_stream*>(context), Z_SYNC_FLUSH);
83
84 uint32_t post_pos = FlateGetPossiblyTruncatedTotalOut(context);
85 ASSERT(post_pos >= pre_pos);
86
87 uint32_t written = post_pos - pre_pos;
88 if (written < dest_size)
89 memset(dest_buf + written, '\0', dest_size - written);
90
91 return ret;
92 }
93
FlateGetAvailOut(void * context)94 uint32_t FlateGetAvailOut(void* context) {
95 return static_cast<z_stream*>(context)->avail_out;
96 }
97
FlateEnd(void * context)98 void FlateEnd(void* context) {
99 inflateEnd(static_cast<z_stream*>(context));
100 static_cast<z_stream*>(context)->zfree(0, context);
101 }
102
103 class CLZWDecoder {
104 public:
105 int Decode(uint8_t* output,
106 uint32_t& outlen,
107 const uint8_t* input,
108 uint32_t& size,
109 bool bEarlyChange);
110
111 private:
112 void AddCode(uint32_t prefix_code, uint8_t append_char);
113 void DecodeString(uint32_t code);
114
115 uint32_t m_InPos;
116 uint32_t m_OutPos;
117 uint8_t* m_pOutput;
118 const uint8_t* m_pInput;
119 bool m_Early;
120 uint32_t m_CodeArray[5021];
121 uint32_t m_nCodes;
122 uint8_t m_DecodeStack[4000];
123 uint32_t m_StackLen;
124 int m_CodeLen;
125 };
126
AddCode(uint32_t prefix_code,uint8_t append_char)127 void CLZWDecoder::AddCode(uint32_t prefix_code, uint8_t append_char) {
128 if (m_nCodes + m_Early == 4094) {
129 return;
130 }
131 m_CodeArray[m_nCodes++] = (prefix_code << 16) | append_char;
132 if (m_nCodes + m_Early == 512 - 258) {
133 m_CodeLen = 10;
134 } else if (m_nCodes + m_Early == 1024 - 258) {
135 m_CodeLen = 11;
136 } else if (m_nCodes + m_Early == 2048 - 258) {
137 m_CodeLen = 12;
138 }
139 }
DecodeString(uint32_t code)140 void CLZWDecoder::DecodeString(uint32_t code) {
141 while (1) {
142 int index = code - 258;
143 if (index < 0 || index >= (int)m_nCodes) {
144 break;
145 }
146 uint32_t data = m_CodeArray[index];
147 if (m_StackLen >= sizeof(m_DecodeStack)) {
148 return;
149 }
150 m_DecodeStack[m_StackLen++] = (uint8_t)data;
151 code = data >> 16;
152 }
153 if (m_StackLen >= sizeof(m_DecodeStack)) {
154 return;
155 }
156 m_DecodeStack[m_StackLen++] = (uint8_t)code;
157 }
Decode(uint8_t * dest_buf,uint32_t & dest_size,const uint8_t * src_buf,uint32_t & src_size,bool bEarlyChange)158 int CLZWDecoder::Decode(uint8_t* dest_buf,
159 uint32_t& dest_size,
160 const uint8_t* src_buf,
161 uint32_t& src_size,
162 bool bEarlyChange) {
163 m_CodeLen = 9;
164 m_InPos = 0;
165 m_OutPos = 0;
166 m_pInput = src_buf;
167 m_pOutput = dest_buf;
168 m_Early = bEarlyChange ? 1 : 0;
169 m_nCodes = 0;
170 uint32_t old_code = 0xFFFFFFFF;
171 uint8_t last_char = 0;
172 while (1) {
173 if (m_InPos + m_CodeLen > src_size * 8) {
174 break;
175 }
176 int byte_pos = m_InPos / 8;
177 int bit_pos = m_InPos % 8, bit_left = m_CodeLen;
178 uint32_t code = 0;
179 if (bit_pos) {
180 bit_left -= 8 - bit_pos;
181 code = (m_pInput[byte_pos++] & ((1 << (8 - bit_pos)) - 1)) << bit_left;
182 }
183 if (bit_left < 8) {
184 code |= m_pInput[byte_pos] >> (8 - bit_left);
185 } else {
186 bit_left -= 8;
187 code |= m_pInput[byte_pos++] << bit_left;
188 if (bit_left) {
189 code |= m_pInput[byte_pos] >> (8 - bit_left);
190 }
191 }
192 m_InPos += m_CodeLen;
193 if (code == 257)
194 break;
195 if (code < 256) {
196 if (m_OutPos == dest_size) {
197 return -5;
198 }
199 if (m_pOutput) {
200 m_pOutput[m_OutPos] = (uint8_t)code;
201 }
202 m_OutPos++;
203 last_char = (uint8_t)code;
204 if (old_code != 0xFFFFFFFF)
205 AddCode(old_code, last_char);
206 old_code = code;
207 } else if (code == 256) {
208 m_CodeLen = 9;
209 m_nCodes = 0;
210 old_code = 0xFFFFFFFF;
211 } else {
212 // Else 257 or greater.
213 if (old_code == 0xFFFFFFFF)
214 return 2;
215
216 m_StackLen = 0;
217 if (code >= m_nCodes + 258) {
218 if (m_StackLen < sizeof(m_DecodeStack)) {
219 m_DecodeStack[m_StackLen++] = last_char;
220 }
221 DecodeString(old_code);
222 } else {
223 DecodeString(code);
224 }
225 if (m_OutPos + m_StackLen > dest_size) {
226 return -5;
227 }
228 if (m_pOutput) {
229 for (uint32_t i = 0; i < m_StackLen; i++) {
230 m_pOutput[m_OutPos + i] = m_DecodeStack[m_StackLen - i - 1];
231 }
232 }
233 m_OutPos += m_StackLen;
234 last_char = m_DecodeStack[m_StackLen - 1];
235 if (old_code < 256) {
236 AddCode(old_code, last_char);
237 } else if (old_code - 258 >= m_nCodes) {
238 dest_size = m_OutPos;
239 src_size = (m_InPos + 7) / 8;
240 return 0;
241 } else {
242 AddCode(old_code, last_char);
243 }
244 old_code = code;
245 }
246 }
247 dest_size = m_OutPos;
248 src_size = (m_InPos + 7) / 8;
249 return 0;
250 }
251
PathPredictor(int a,int b,int c)252 uint8_t PathPredictor(int a, int b, int c) {
253 int p = a + b - c;
254 int pa = abs(p - a);
255 int pb = abs(p - b);
256 int pc = abs(p - c);
257 if (pa <= pb && pa <= pc)
258 return (uint8_t)a;
259 if (pb <= pc)
260 return (uint8_t)b;
261 return (uint8_t)c;
262 }
263
PNG_PredictorEncode(uint8_t ** data_buf,uint32_t * data_size)264 void PNG_PredictorEncode(uint8_t** data_buf, uint32_t* data_size) {
265 const int row_size = 7;
266 const int row_count = (*data_size + row_size - 1) / row_size;
267 const int last_row_size = *data_size % row_size;
268 uint8_t* dest_buf = FX_Alloc2D(uint8_t, row_size + 1, row_count);
269 int byte_cnt = 0;
270 uint8_t* pSrcData = *data_buf;
271 uint8_t* pDestData = dest_buf;
272 for (int row = 0; row < row_count; row++) {
273 for (int byte = 0; byte < row_size && byte_cnt < (int)*data_size; byte++) {
274 pDestData[0] = 2;
275 uint8_t up = 0;
276 if (row)
277 up = pSrcData[byte - row_size];
278 pDestData[byte + 1] = pSrcData[byte] - up;
279 ++byte_cnt;
280 }
281 pDestData += (row_size + 1);
282 pSrcData += row_size;
283 }
284 FX_Free(*data_buf);
285 *data_buf = dest_buf;
286 *data_size = (row_size + 1) * row_count -
287 (last_row_size > 0 ? (row_size - last_row_size) : 0);
288 }
289
PNG_PredictLine(uint8_t * pDestData,const uint8_t * pSrcData,const uint8_t * pLastLine,int bpc,int nColors,int nPixels)290 void PNG_PredictLine(uint8_t* pDestData,
291 const uint8_t* pSrcData,
292 const uint8_t* pLastLine,
293 int bpc,
294 int nColors,
295 int nPixels) {
296 int row_size = (nPixels * bpc * nColors + 7) / 8;
297 int BytesPerPixel = (bpc * nColors + 7) / 8;
298 uint8_t tag = pSrcData[0];
299 if (tag == 0) {
300 memmove(pDestData, pSrcData + 1, row_size);
301 return;
302 }
303 for (int byte = 0; byte < row_size; byte++) {
304 uint8_t raw_byte = pSrcData[byte + 1];
305 switch (tag) {
306 case 1: {
307 uint8_t left = 0;
308 if (byte >= BytesPerPixel) {
309 left = pDestData[byte - BytesPerPixel];
310 }
311 pDestData[byte] = raw_byte + left;
312 break;
313 }
314 case 2: {
315 uint8_t up = 0;
316 if (pLastLine) {
317 up = pLastLine[byte];
318 }
319 pDestData[byte] = raw_byte + up;
320 break;
321 }
322 case 3: {
323 uint8_t left = 0;
324 if (byte >= BytesPerPixel) {
325 left = pDestData[byte - BytesPerPixel];
326 }
327 uint8_t up = 0;
328 if (pLastLine) {
329 up = pLastLine[byte];
330 }
331 pDestData[byte] = raw_byte + (up + left) / 2;
332 break;
333 }
334 case 4: {
335 uint8_t left = 0;
336 if (byte >= BytesPerPixel) {
337 left = pDestData[byte - BytesPerPixel];
338 }
339 uint8_t up = 0;
340 if (pLastLine) {
341 up = pLastLine[byte];
342 }
343 uint8_t upper_left = 0;
344 if (byte >= BytesPerPixel && pLastLine) {
345 upper_left = pLastLine[byte - BytesPerPixel];
346 }
347 pDestData[byte] = raw_byte + PathPredictor(left, up, upper_left);
348 break;
349 }
350 default:
351 pDestData[byte] = raw_byte;
352 break;
353 }
354 }
355 }
356
PNG_Predictor(uint8_t * & data_buf,uint32_t & data_size,int Colors,int BitsPerComponent,int Columns)357 bool PNG_Predictor(uint8_t*& data_buf,
358 uint32_t& data_size,
359 int Colors,
360 int BitsPerComponent,
361 int Columns) {
362 const int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8;
363 const int row_size = (Colors * BitsPerComponent * Columns + 7) / 8;
364 if (row_size <= 0)
365 return false;
366 const int row_count = (data_size + row_size) / (row_size + 1);
367 if (row_count <= 0)
368 return false;
369 const int last_row_size = data_size % (row_size + 1);
370 uint8_t* dest_buf = FX_Alloc2D(uint8_t, row_size, row_count);
371 int byte_cnt = 0;
372 uint8_t* pSrcData = data_buf;
373 uint8_t* pDestData = dest_buf;
374 for (int row = 0; row < row_count; row++) {
375 uint8_t tag = pSrcData[0];
376 byte_cnt++;
377 if (tag == 0) {
378 int move_size = row_size;
379 if ((row + 1) * (move_size + 1) > (int)data_size) {
380 move_size = last_row_size - 1;
381 }
382 memmove(pDestData, pSrcData + 1, move_size);
383 pSrcData += move_size + 1;
384 pDestData += move_size;
385 byte_cnt += move_size;
386 continue;
387 }
388 for (int byte = 0; byte < row_size && byte_cnt < (int)data_size; byte++) {
389 uint8_t raw_byte = pSrcData[byte + 1];
390 switch (tag) {
391 case 1: {
392 uint8_t left = 0;
393 if (byte >= BytesPerPixel) {
394 left = pDestData[byte - BytesPerPixel];
395 }
396 pDestData[byte] = raw_byte + left;
397 break;
398 }
399 case 2: {
400 uint8_t up = 0;
401 if (row) {
402 up = pDestData[byte - row_size];
403 }
404 pDestData[byte] = raw_byte + up;
405 break;
406 }
407 case 3: {
408 uint8_t left = 0;
409 if (byte >= BytesPerPixel) {
410 left = pDestData[byte - BytesPerPixel];
411 }
412 uint8_t up = 0;
413 if (row) {
414 up = pDestData[byte - row_size];
415 }
416 pDestData[byte] = raw_byte + (up + left) / 2;
417 break;
418 }
419 case 4: {
420 uint8_t left = 0;
421 if (byte >= BytesPerPixel) {
422 left = pDestData[byte - BytesPerPixel];
423 }
424 uint8_t up = 0;
425 if (row) {
426 up = pDestData[byte - row_size];
427 }
428 uint8_t upper_left = 0;
429 if (byte >= BytesPerPixel && row) {
430 upper_left = pDestData[byte - row_size - BytesPerPixel];
431 }
432 pDestData[byte] = raw_byte + PathPredictor(left, up, upper_left);
433 break;
434 }
435 default:
436 pDestData[byte] = raw_byte;
437 break;
438 }
439 byte_cnt++;
440 }
441 pSrcData += row_size + 1;
442 pDestData += row_size;
443 }
444 FX_Free(data_buf);
445 data_buf = dest_buf;
446 data_size = row_size * row_count -
447 (last_row_size > 0 ? (row_size + 1 - last_row_size) : 0);
448 return true;
449 }
450
TIFF_PredictLine(uint8_t * dest_buf,uint32_t row_size,int BitsPerComponent,int Colors,int Columns)451 void TIFF_PredictLine(uint8_t* dest_buf,
452 uint32_t row_size,
453 int BitsPerComponent,
454 int Colors,
455 int Columns) {
456 if (BitsPerComponent == 1) {
457 int row_bits = std::min(BitsPerComponent * Colors * Columns,
458 pdfium::base::checked_cast<int>(row_size * 8));
459 int index_pre = 0;
460 int col_pre = 0;
461 for (int i = 1; i < row_bits; i++) {
462 int col = i % 8;
463 int index = i / 8;
464 if (((dest_buf[index] >> (7 - col)) & 1) ^
465 ((dest_buf[index_pre] >> (7 - col_pre)) & 1)) {
466 dest_buf[index] |= 1 << (7 - col);
467 } else {
468 dest_buf[index] &= ~(1 << (7 - col));
469 }
470 index_pre = index;
471 col_pre = col;
472 }
473 return;
474 }
475 int BytesPerPixel = BitsPerComponent * Colors / 8;
476 if (BitsPerComponent == 16) {
477 for (uint32_t i = BytesPerPixel; i + 1 < row_size; i += 2) {
478 uint16_t pixel =
479 (dest_buf[i - BytesPerPixel] << 8) | dest_buf[i - BytesPerPixel + 1];
480 pixel += (dest_buf[i] << 8) | dest_buf[i + 1];
481 dest_buf[i] = pixel >> 8;
482 dest_buf[i + 1] = (uint8_t)pixel;
483 }
484 } else {
485 for (uint32_t i = BytesPerPixel; i < row_size; i++) {
486 dest_buf[i] += dest_buf[i - BytesPerPixel];
487 }
488 }
489 }
490
TIFF_Predictor(uint8_t * & data_buf,uint32_t & data_size,int Colors,int BitsPerComponent,int Columns)491 bool TIFF_Predictor(uint8_t*& data_buf,
492 uint32_t& data_size,
493 int Colors,
494 int BitsPerComponent,
495 int Columns) {
496 int row_size = (Colors * BitsPerComponent * Columns + 7) / 8;
497 if (row_size == 0)
498 return false;
499 const int row_count = (data_size + row_size - 1) / row_size;
500 const int last_row_size = data_size % row_size;
501 for (int row = 0; row < row_count; row++) {
502 uint8_t* scan_line = data_buf + row * row_size;
503 if ((row + 1) * row_size > (int)data_size) {
504 row_size = last_row_size;
505 }
506 TIFF_PredictLine(scan_line, row_size, BitsPerComponent, Colors, Columns);
507 }
508 return true;
509 }
510
FlateUncompress(const uint8_t * src_buf,uint32_t src_size,uint32_t orig_size,uint8_t * & dest_buf,uint32_t & dest_size,uint32_t & offset)511 void FlateUncompress(const uint8_t* src_buf,
512 uint32_t src_size,
513 uint32_t orig_size,
514 uint8_t*& dest_buf,
515 uint32_t& dest_size,
516 uint32_t& offset) {
517 dest_buf = nullptr;
518 dest_size = 0;
519 void* context = FlateInit();
520 if (!context)
521 return;
522
523 FlateInput(context, src_buf, src_size);
524
525 const uint32_t kMaxInitialAllocSize = 10000000;
526 uint32_t guess_size = orig_size ? orig_size : src_size * 2;
527 guess_size = std::min(guess_size, kMaxInitialAllocSize);
528
529 uint32_t buf_size = guess_size;
530 uint32_t last_buf_size = buf_size;
531 std::unique_ptr<uint8_t, FxFreeDeleter> guess_buf(
532 FX_Alloc(uint8_t, guess_size + 1));
533 guess_buf.get()[guess_size] = '\0';
534
535 std::vector<uint8_t*> result_tmp_bufs;
536 uint8_t* cur_buf = guess_buf.release();
537 while (1) {
538 uint32_t ret = FlateOutput(context, cur_buf, buf_size);
539 uint32_t avail_buf_size = FlateGetAvailOut(context);
540 if (ret != Z_OK || avail_buf_size != 0) {
541 last_buf_size = buf_size - avail_buf_size;
542 result_tmp_bufs.push_back(cur_buf);
543 break;
544 }
545 result_tmp_bufs.push_back(cur_buf);
546 cur_buf = FX_Alloc(uint8_t, buf_size + 1);
547 cur_buf[buf_size] = '\0';
548 }
549
550 // The TotalOut size returned from the library may not be big enough to
551 // handle the content the library returns. We can only handle items
552 // up to 4GB in size.
553 dest_size = FlateGetPossiblyTruncatedTotalOut(context);
554 offset = FlateGetPossiblyTruncatedTotalIn(context);
555 if (result_tmp_bufs.size() == 1) {
556 dest_buf = result_tmp_bufs[0];
557 } else {
558 uint8_t* result_buf = FX_Alloc(uint8_t, dest_size);
559 uint32_t result_pos = 0;
560 uint32_t remaining = dest_size;
561 for (size_t i = 0; i < result_tmp_bufs.size(); i++) {
562 uint8_t* tmp_buf = result_tmp_bufs[i];
563 uint32_t tmp_buf_size = buf_size;
564 if (i == result_tmp_bufs.size() - 1)
565 tmp_buf_size = last_buf_size;
566
567 uint32_t cp_size = std::min(tmp_buf_size, remaining);
568 memcpy(result_buf + result_pos, tmp_buf, cp_size);
569 result_pos += cp_size;
570 remaining -= cp_size;
571
572 FX_Free(result_tmp_bufs[i]);
573 }
574 dest_buf = result_buf;
575 }
576 FlateEnd(context);
577 }
578
579 } // namespace
580
581 class CCodec_FlateScanlineDecoder : public CCodec_ScanlineDecoder {
582 public:
583 CCodec_FlateScanlineDecoder();
584 ~CCodec_FlateScanlineDecoder() override;
585
586 void Create(const uint8_t* src_buf,
587 uint32_t src_size,
588 int width,
589 int height,
590 int nComps,
591 int bpc,
592 int predictor,
593 int Colors,
594 int BitsPerComponent,
595 int Columns);
596
597 // CCodec_ScanlineDecoder
598 bool v_Rewind() override;
599 uint8_t* v_GetNextLine() override;
600 uint32_t GetSrcOffset() override;
601
602 void* m_pFlate;
603 const uint8_t* m_SrcBuf;
604 uint32_t m_SrcSize;
605 uint8_t* m_pScanline;
606 uint8_t* m_pLastLine;
607 uint8_t* m_pPredictBuffer;
608 uint8_t* m_pPredictRaw;
609 int m_Predictor;
610 int m_Colors;
611 int m_BitsPerComponent;
612 int m_Columns;
613 uint32_t m_PredictPitch;
614 size_t m_LeftOver;
615 };
616
CCodec_FlateScanlineDecoder()617 CCodec_FlateScanlineDecoder::CCodec_FlateScanlineDecoder() {
618 m_pFlate = nullptr;
619 m_pScanline = nullptr;
620 m_pLastLine = nullptr;
621 m_pPredictBuffer = nullptr;
622 m_pPredictRaw = nullptr;
623 m_LeftOver = 0;
624 }
625
~CCodec_FlateScanlineDecoder()626 CCodec_FlateScanlineDecoder::~CCodec_FlateScanlineDecoder() {
627 FX_Free(m_pScanline);
628 FX_Free(m_pLastLine);
629 FX_Free(m_pPredictBuffer);
630 FX_Free(m_pPredictRaw);
631 if (m_pFlate)
632 FlateEnd(m_pFlate);
633 }
634
Create(const uint8_t * src_buf,uint32_t src_size,int width,int height,int nComps,int bpc,int predictor,int Colors,int BitsPerComponent,int Columns)635 void CCodec_FlateScanlineDecoder::Create(const uint8_t* src_buf,
636 uint32_t src_size,
637 int width,
638 int height,
639 int nComps,
640 int bpc,
641 int predictor,
642 int Colors,
643 int BitsPerComponent,
644 int Columns) {
645 m_SrcBuf = src_buf;
646 m_SrcSize = src_size;
647 m_OutputWidth = m_OrigWidth = width;
648 m_OutputHeight = m_OrigHeight = height;
649 m_nComps = nComps;
650 m_bpc = bpc;
651 m_Pitch = (static_cast<uint32_t>(width) * nComps * bpc + 7) / 8;
652 m_pScanline = FX_Alloc(uint8_t, m_Pitch);
653 m_Predictor = 0;
654 if (predictor) {
655 if (predictor >= 10) {
656 m_Predictor = 2;
657 } else if (predictor == 2) {
658 m_Predictor = 1;
659 }
660 if (m_Predictor) {
661 if (BitsPerComponent * Colors * Columns == 0) {
662 BitsPerComponent = m_bpc;
663 Colors = m_nComps;
664 Columns = m_OrigWidth;
665 }
666 m_Colors = Colors;
667 m_BitsPerComponent = BitsPerComponent;
668 m_Columns = Columns;
669 m_PredictPitch =
670 (static_cast<uint32_t>(m_BitsPerComponent) * m_Colors * m_Columns +
671 7) /
672 8;
673 m_pLastLine = FX_Alloc(uint8_t, m_PredictPitch);
674 m_pPredictRaw = FX_Alloc(uint8_t, m_PredictPitch + 1);
675 m_pPredictBuffer = FX_Alloc(uint8_t, m_PredictPitch);
676 }
677 }
678 }
679
v_Rewind()680 bool CCodec_FlateScanlineDecoder::v_Rewind() {
681 if (m_pFlate)
682 FlateEnd(m_pFlate);
683
684 m_pFlate = FlateInit();
685 if (!m_pFlate)
686 return false;
687
688 FlateInput(m_pFlate, m_SrcBuf, m_SrcSize);
689 m_LeftOver = 0;
690 return true;
691 }
692
v_GetNextLine()693 uint8_t* CCodec_FlateScanlineDecoder::v_GetNextLine() {
694 if (m_Predictor) {
695 if (m_Pitch == m_PredictPitch) {
696 if (m_Predictor == 2) {
697 FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1);
698 PNG_PredictLine(m_pScanline, m_pPredictRaw, m_pLastLine,
699 m_BitsPerComponent, m_Colors, m_Columns);
700 memcpy(m_pLastLine, m_pScanline, m_PredictPitch);
701 } else {
702 FlateOutput(m_pFlate, m_pScanline, m_Pitch);
703 TIFF_PredictLine(m_pScanline, m_PredictPitch, m_bpc, m_nComps,
704 m_OutputWidth);
705 }
706 } else {
707 size_t bytes_to_go = m_Pitch;
708 size_t read_leftover =
709 m_LeftOver > bytes_to_go ? bytes_to_go : m_LeftOver;
710 if (read_leftover) {
711 memcpy(m_pScanline, m_pPredictBuffer + m_PredictPitch - m_LeftOver,
712 read_leftover);
713 m_LeftOver -= read_leftover;
714 bytes_to_go -= read_leftover;
715 }
716 while (bytes_to_go) {
717 if (m_Predictor == 2) {
718 FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1);
719 PNG_PredictLine(m_pPredictBuffer, m_pPredictRaw, m_pLastLine,
720 m_BitsPerComponent, m_Colors, m_Columns);
721 memcpy(m_pLastLine, m_pPredictBuffer, m_PredictPitch);
722 } else {
723 FlateOutput(m_pFlate, m_pPredictBuffer, m_PredictPitch);
724 TIFF_PredictLine(m_pPredictBuffer, m_PredictPitch, m_BitsPerComponent,
725 m_Colors, m_Columns);
726 }
727 size_t read_bytes =
728 m_PredictPitch > bytes_to_go ? bytes_to_go : m_PredictPitch;
729 memcpy(m_pScanline + m_Pitch - bytes_to_go, m_pPredictBuffer,
730 read_bytes);
731 m_LeftOver += m_PredictPitch - read_bytes;
732 bytes_to_go -= read_bytes;
733 }
734 }
735 } else {
736 FlateOutput(m_pFlate, m_pScanline, m_Pitch);
737 }
738 return m_pScanline;
739 }
740
GetSrcOffset()741 uint32_t CCodec_FlateScanlineDecoder::GetSrcOffset() {
742 return FlateGetPossiblyTruncatedTotalIn(m_pFlate);
743 }
744
CreateDecoder(const uint8_t * src_buf,uint32_t src_size,int width,int height,int nComps,int bpc,int predictor,int Colors,int BitsPerComponent,int Columns)745 std::unique_ptr<CCodec_ScanlineDecoder> CCodec_FlateModule::CreateDecoder(
746 const uint8_t* src_buf,
747 uint32_t src_size,
748 int width,
749 int height,
750 int nComps,
751 int bpc,
752 int predictor,
753 int Colors,
754 int BitsPerComponent,
755 int Columns) {
756 auto pDecoder = pdfium::MakeUnique<CCodec_FlateScanlineDecoder>();
757 pDecoder->Create(src_buf, src_size, width, height, nComps, bpc, predictor,
758 Colors, BitsPerComponent, Columns);
759 return std::move(pDecoder);
760 }
761
FlateOrLZWDecode(bool bLZW,const uint8_t * src_buf,uint32_t src_size,bool bEarlyChange,int predictor,int Colors,int BitsPerComponent,int Columns,uint32_t estimated_size,uint8_t ** dest_buf,uint32_t * dest_size)762 uint32_t CCodec_FlateModule::FlateOrLZWDecode(bool bLZW,
763 const uint8_t* src_buf,
764 uint32_t src_size,
765 bool bEarlyChange,
766 int predictor,
767 int Colors,
768 int BitsPerComponent,
769 int Columns,
770 uint32_t estimated_size,
771 uint8_t** dest_buf,
772 uint32_t* dest_size) {
773 *dest_buf = nullptr;
774 uint32_t offset = 0;
775 int predictor_type = 0;
776 if (predictor) {
777 if (predictor >= 10)
778 predictor_type = 2;
779 else if (predictor == 2)
780 predictor_type = 1;
781 }
782 if (bLZW) {
783 auto decoder = pdfium::MakeUnique<CLZWDecoder>();
784 *dest_size = 0xFFFFFFFF;
785 offset = src_size;
786 int err =
787 decoder->Decode(nullptr, *dest_size, src_buf, offset, bEarlyChange);
788 if (err || *dest_size == 0 || *dest_size + 1 < *dest_size)
789 return FX_INVALID_OFFSET;
790
791 decoder = pdfium::MakeUnique<CLZWDecoder>();
792 *dest_buf = FX_Alloc(uint8_t, *dest_size + 1);
793 (*dest_buf)[*dest_size] = '\0';
794 decoder->Decode(*dest_buf, *dest_size, src_buf, offset, bEarlyChange);
795 } else {
796 FlateUncompress(src_buf, src_size, estimated_size, *dest_buf, *dest_size,
797 offset);
798 }
799 if (predictor_type == 0)
800 return offset;
801
802 bool ret = true;
803 if (predictor_type == 2) {
804 ret =
805 PNG_Predictor(*dest_buf, *dest_size, Colors, BitsPerComponent, Columns);
806 } else if (predictor_type == 1) {
807 ret = TIFF_Predictor(*dest_buf, *dest_size, Colors, BitsPerComponent,
808 Columns);
809 }
810 return ret ? offset : FX_INVALID_OFFSET;
811 }
812
Encode(const uint8_t * src_buf,uint32_t src_size,uint8_t ** dest_buf,uint32_t * dest_size)813 bool CCodec_FlateModule::Encode(const uint8_t* src_buf,
814 uint32_t src_size,
815 uint8_t** dest_buf,
816 uint32_t* dest_size) {
817 *dest_size = src_size + src_size / 1000 + 12;
818 *dest_buf = FX_Alloc(uint8_t, *dest_size);
819 unsigned long temp_size = *dest_size;
820 if (!FlateCompress(*dest_buf, &temp_size, src_buf, src_size))
821 return false;
822
823 *dest_size = (uint32_t)temp_size;
824 return true;
825 }
826
PngEncode(const uint8_t * src_buf,uint32_t src_size,uint8_t ** dest_buf,uint32_t * dest_size)827 bool CCodec_FlateModule::PngEncode(const uint8_t* src_buf,
828 uint32_t src_size,
829 uint8_t** dest_buf,
830 uint32_t* dest_size) {
831 uint8_t* pSrcBuf = FX_Alloc(uint8_t, src_size);
832 memcpy(pSrcBuf, src_buf, src_size);
833 PNG_PredictorEncode(&pSrcBuf, &src_size);
834 bool ret = Encode(pSrcBuf, src_size, dest_buf, dest_size);
835 FX_Free(pSrcBuf);
836 return ret;
837 }
838