• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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