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