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