• 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/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