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