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/include/fx_codec.h"
8 
9 #include <cmath>
10 #include <memory>
11 #include <utility>
12 
13 #include "core/fxcodec/codec/codec_int.h"
14 #include "core/fxcrt/include/fx_ext.h"
15 #include "core/fxcrt/include/fx_safe_types.h"
16 #include "third_party/base/logging.h"
17 
CCodec_ModuleMgr()18 CCodec_ModuleMgr::CCodec_ModuleMgr()
19     : m_pBasicModule(new CCodec_BasicModule),
20       m_pFaxModule(new CCodec_FaxModule),
21       m_pJpegModule(new CCodec_JpegModule),
22       m_pJpxModule(new CCodec_JpxModule),
23       m_pJbig2Module(new CCodec_Jbig2Module),
24       m_pIccModule(new CCodec_IccModule),
25 #ifdef PDF_ENABLE_XFA
26       m_pPngModule(new CCodec_PngModule),
27       m_pGifModule(new CCodec_GifModule),
28       m_pBmpModule(new CCodec_BmpModule),
29       m_pTiffModule(new CCodec_TiffModule),
30 #endif  // PDF_ENABLE_XFA
31       m_pFlateModule(new CCodec_FlateModule) {
32 }
33 
~CCodec_ModuleMgr()34 CCodec_ModuleMgr::~CCodec_ModuleMgr() {}
35 
CCodec_ScanlineDecoder()36 CCodec_ScanlineDecoder::CCodec_ScanlineDecoder()
37     : m_NextLine(-1), m_pLastScanline(nullptr) {}
38 
~CCodec_ScanlineDecoder()39 CCodec_ScanlineDecoder::~CCodec_ScanlineDecoder() {}
40 
GetScanline(int line)41 const uint8_t* CCodec_ScanlineDecoder::GetScanline(int line) {
42   if (m_NextLine == line + 1)
43     return m_pLastScanline;
44 
45   if (m_NextLine < 0 || m_NextLine > line) {
46     if (!v_Rewind())
47       return nullptr;
48     m_NextLine = 0;
49   }
50   while (m_NextLine < line) {
51     ReadNextLine();
52     m_NextLine++;
53   }
54   m_pLastScanline = ReadNextLine();
55   m_NextLine++;
56   return m_pLastScanline;
57 }
58 
SkipToScanline(int line,IFX_Pause * pPause)59 FX_BOOL CCodec_ScanlineDecoder::SkipToScanline(int line, IFX_Pause* pPause) {
60   if (m_NextLine == line || m_NextLine == line + 1)
61     return FALSE;
62 
63   if (m_NextLine < 0 || m_NextLine > line) {
64     v_Rewind();
65     m_NextLine = 0;
66   }
67   m_pLastScanline = nullptr;
68   while (m_NextLine < line) {
69     m_pLastScanline = ReadNextLine();
70     m_NextLine++;
71     if (pPause && pPause->NeedToPauseNow()) {
72       return TRUE;
73     }
74   }
75   return FALSE;
76 }
77 
ReadNextLine()78 uint8_t* CCodec_ScanlineDecoder::ReadNextLine() {
79   return v_GetNextLine();
80 }
81 
82 #ifdef PDF_ENABLE_XFA
CFX_DIBAttribute()83 CFX_DIBAttribute::CFX_DIBAttribute()
84     : m_nXDPI(-1),
85       m_nYDPI(-1),
86       m_fAspectRatio(-1.0f),
87       m_wDPIUnit(0),
88       m_nGifLeft(0),
89       m_nGifTop(0),
90       m_pGifLocalPalette(nullptr),
91       m_nGifLocalPalNum(0),
92       m_nBmpCompressType(0) {
93   FXSYS_memset(m_strTime, 0, sizeof(m_strTime));
94 }
~CFX_DIBAttribute()95 CFX_DIBAttribute::~CFX_DIBAttribute() {
96   for (const auto& pair : m_Exif)
97     FX_Free(pair.second);
98 }
99 #endif  // PDF_ENABLE_XFA
100 
101 class CCodec_RLScanlineDecoder : public CCodec_ScanlineDecoder {
102  public:
103   CCodec_RLScanlineDecoder();
104   ~CCodec_RLScanlineDecoder() override;
105 
106   FX_BOOL Create(const uint8_t* src_buf,
107                  uint32_t src_size,
108                  int width,
109                  int height,
110                  int nComps,
111                  int bpc);
112 
113   // CCodec_ScanlineDecoder
114   FX_BOOL v_Rewind() override;
115   uint8_t* v_GetNextLine() override;
GetSrcOffset()116   uint32_t GetSrcOffset() override { return m_SrcOffset; }
117 
118  protected:
119   FX_BOOL CheckDestSize();
120   void GetNextOperator();
121   void UpdateOperator(uint8_t used_bytes);
122 
123   uint8_t* m_pScanline;
124   const uint8_t* m_pSrcBuf;
125   uint32_t m_SrcSize;
126   uint32_t m_dwLineBytes;
127   uint32_t m_SrcOffset;
128   FX_BOOL m_bEOD;
129   uint8_t m_Operator;
130 };
CCodec_RLScanlineDecoder()131 CCodec_RLScanlineDecoder::CCodec_RLScanlineDecoder()
132     : m_pScanline(nullptr),
133       m_pSrcBuf(nullptr),
134       m_SrcSize(0),
135       m_dwLineBytes(0),
136       m_SrcOffset(0),
137       m_bEOD(FALSE),
138       m_Operator(0) {}
~CCodec_RLScanlineDecoder()139 CCodec_RLScanlineDecoder::~CCodec_RLScanlineDecoder() {
140   FX_Free(m_pScanline);
141 }
CheckDestSize()142 FX_BOOL CCodec_RLScanlineDecoder::CheckDestSize() {
143   uint32_t i = 0;
144   uint32_t old_size = 0;
145   uint32_t dest_size = 0;
146   while (i < m_SrcSize) {
147     if (m_pSrcBuf[i] < 128) {
148       old_size = dest_size;
149       dest_size += m_pSrcBuf[i] + 1;
150       if (dest_size < old_size) {
151         return FALSE;
152       }
153       i += m_pSrcBuf[i] + 2;
154     } else if (m_pSrcBuf[i] > 128) {
155       old_size = dest_size;
156       dest_size += 257 - m_pSrcBuf[i];
157       if (dest_size < old_size) {
158         return FALSE;
159       }
160       i += 2;
161     } else {
162       break;
163     }
164   }
165   if (((uint32_t)m_OrigWidth * m_nComps * m_bpc * m_OrigHeight + 7) / 8 >
166       dest_size) {
167     return FALSE;
168   }
169   return TRUE;
170 }
Create(const uint8_t * src_buf,uint32_t src_size,int width,int height,int nComps,int bpc)171 FX_BOOL CCodec_RLScanlineDecoder::Create(const uint8_t* src_buf,
172                                          uint32_t src_size,
173                                          int width,
174                                          int height,
175                                          int nComps,
176                                          int bpc) {
177   m_pSrcBuf = src_buf;
178   m_SrcSize = src_size;
179   m_OutputWidth = m_OrigWidth = width;
180   m_OutputHeight = m_OrigHeight = height;
181   m_nComps = nComps;
182   m_bpc = bpc;
183   // Aligning the pitch to 4 bytes requires an integer overflow check.
184   FX_SAFE_UINT32 pitch = width;
185   pitch *= nComps;
186   pitch *= bpc;
187   pitch += 31;
188   pitch /= 32;
189   pitch *= 4;
190   if (!pitch.IsValid()) {
191     return FALSE;
192   }
193   m_Pitch = pitch.ValueOrDie();
194   // Overflow should already have been checked before this is called.
195   m_dwLineBytes = (static_cast<uint32_t>(width) * nComps * bpc + 7) / 8;
196   m_pScanline = FX_Alloc(uint8_t, m_Pitch);
197   return CheckDestSize();
198 }
v_Rewind()199 FX_BOOL CCodec_RLScanlineDecoder::v_Rewind() {
200   FXSYS_memset(m_pScanline, 0, m_Pitch);
201   m_SrcOffset = 0;
202   m_bEOD = FALSE;
203   m_Operator = 0;
204   return TRUE;
205 }
v_GetNextLine()206 uint8_t* CCodec_RLScanlineDecoder::v_GetNextLine() {
207   if (m_SrcOffset == 0) {
208     GetNextOperator();
209   } else {
210     if (m_bEOD) {
211       return nullptr;
212     }
213   }
214   FXSYS_memset(m_pScanline, 0, m_Pitch);
215   uint32_t col_pos = 0;
216   FX_BOOL eol = FALSE;
217   while (m_SrcOffset < m_SrcSize && !eol) {
218     if (m_Operator < 128) {
219       uint32_t copy_len = m_Operator + 1;
220       if (col_pos + copy_len >= m_dwLineBytes) {
221         copy_len = m_dwLineBytes - col_pos;
222         eol = TRUE;
223       }
224       if (copy_len >= m_SrcSize - m_SrcOffset) {
225         copy_len = m_SrcSize - m_SrcOffset;
226         m_bEOD = TRUE;
227       }
228       FXSYS_memcpy(m_pScanline + col_pos, m_pSrcBuf + m_SrcOffset, copy_len);
229       col_pos += copy_len;
230       UpdateOperator((uint8_t)copy_len);
231     } else if (m_Operator > 128) {
232       int fill = 0;
233       if (m_SrcOffset - 1 < m_SrcSize - 1) {
234         fill = m_pSrcBuf[m_SrcOffset];
235       }
236       uint32_t duplicate_len = 257 - m_Operator;
237       if (col_pos + duplicate_len >= m_dwLineBytes) {
238         duplicate_len = m_dwLineBytes - col_pos;
239         eol = TRUE;
240       }
241       FXSYS_memset(m_pScanline + col_pos, fill, duplicate_len);
242       col_pos += duplicate_len;
243       UpdateOperator((uint8_t)duplicate_len);
244     } else {
245       m_bEOD = TRUE;
246       break;
247     }
248   }
249   return m_pScanline;
250 }
GetNextOperator()251 void CCodec_RLScanlineDecoder::GetNextOperator() {
252   if (m_SrcOffset >= m_SrcSize) {
253     m_Operator = 128;
254     return;
255   }
256   m_Operator = m_pSrcBuf[m_SrcOffset];
257   m_SrcOffset++;
258 }
UpdateOperator(uint8_t used_bytes)259 void CCodec_RLScanlineDecoder::UpdateOperator(uint8_t used_bytes) {
260   if (used_bytes == 0) {
261     return;
262   }
263   if (m_Operator < 128) {
264     ASSERT((uint32_t)m_Operator + 1 >= used_bytes);
265     if (used_bytes == m_Operator + 1) {
266       m_SrcOffset += used_bytes;
267       GetNextOperator();
268       return;
269     }
270     m_Operator -= used_bytes;
271     m_SrcOffset += used_bytes;
272     if (m_SrcOffset >= m_SrcSize) {
273       m_Operator = 128;
274     }
275     return;
276   }
277   uint8_t count = 257 - m_Operator;
278   ASSERT((uint32_t)count >= used_bytes);
279   if (used_bytes == count) {
280     m_SrcOffset++;
281     GetNextOperator();
282     return;
283   }
284   count -= used_bytes;
285   m_Operator = 257 - count;
286 }
287 
CreateRunLengthDecoder(const uint8_t * src_buf,uint32_t src_size,int width,int height,int nComps,int bpc)288 CCodec_ScanlineDecoder* CCodec_BasicModule::CreateRunLengthDecoder(
289     const uint8_t* src_buf,
290     uint32_t src_size,
291     int width,
292     int height,
293     int nComps,
294     int bpc) {
295   std::unique_ptr<CCodec_RLScanlineDecoder> pRLScanlineDecoder(
296       new CCodec_RLScanlineDecoder);
297   if (!pRLScanlineDecoder->Create(src_buf, src_size, width, height, nComps,
298                                   bpc)) {
299     return nullptr;
300   }
301 
302   return pRLScanlineDecoder.release();
303 }
304