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