SEGV in CFX_BaseSegmentedArray::Iterate() when CS has malformed dictionary.
[pdfium.git] / core / src / fxcrt / extension.h
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 #ifndef _FXCRT_EXTENSION_IMP_
8 #define _FXCRT_EXTENSION_IMP_
9
10 #include "fx_safe_types.h"
11
12 class IFXCRT_FileAccess
13 {
14 public:
15     virtual ~IFXCRT_FileAccess() {}
16     virtual FX_BOOL             Open(FX_BSTR fileName, FX_DWORD dwMode) = 0;
17     virtual FX_BOOL             Open(FX_WSTR fileName, FX_DWORD dwMode) = 0;
18     virtual void                Close() = 0;
19     virtual void                Release() = 0;
20     virtual FX_FILESIZE GetSize() const = 0;
21     virtual FX_FILESIZE GetPosition() const = 0;
22     virtual FX_FILESIZE SetPosition(FX_FILESIZE pos) = 0;
23     virtual size_t              Read(void* pBuffer, size_t szBuffer) = 0;
24     virtual size_t              Write(const void* pBuffer, size_t szBuffer) = 0;
25     virtual size_t              ReadPos(void* pBuffer, size_t szBuffer, FX_FILESIZE pos) = 0;
26     virtual size_t              WritePos(const void* pBuffer, size_t szBuffer, FX_FILESIZE pos) = 0;
27     virtual FX_BOOL             Flush() = 0;
28     virtual FX_BOOL             Truncate(FX_FILESIZE szFile) = 0;
29 };
30 IFXCRT_FileAccess*      FXCRT_FileAccess_Create();
31 class CFX_CRTFileStream FX_FINAL : public IFX_FileStream
32 {
33 public:
34     CFX_CRTFileStream(IFXCRT_FileAccess* pFA) : m_pFile(pFA), m_dwCount(1), m_bUseRange(FALSE), m_nOffset(0), m_nSize(0) {}
35     ~CFX_CRTFileStream()
36     {
37         if (m_pFile) {
38             m_pFile->Release();
39         }
40     }
41     virtual IFX_FileStream*             Retain() FX_OVERRIDE
42     {
43         m_dwCount ++;
44         return this;
45     }
46     virtual void                                Release() FX_OVERRIDE
47     {
48         FX_DWORD nCount = -- m_dwCount;
49         if (!nCount) {
50             delete this;
51         }
52     }
53     virtual FX_FILESIZE                 GetSize() FX_OVERRIDE
54     {
55         return m_bUseRange ? m_nSize : m_pFile->GetSize();
56     }
57     virtual FX_BOOL                             IsEOF() FX_OVERRIDE
58     {
59         return GetPosition() >= GetSize();
60     }
61     virtual FX_FILESIZE                 GetPosition() FX_OVERRIDE
62     {
63         FX_FILESIZE pos = m_pFile->GetPosition();
64         if (m_bUseRange) {
65             pos -= m_nOffset;
66         }
67         return pos;
68     }
69     virtual FX_BOOL                             SetRange(FX_FILESIZE offset, FX_FILESIZE size) FX_OVERRIDE
70     {
71         if (offset < 0 || size < 0) {
72             return FALSE;
73         }
74      
75         FX_SAFE_FILESIZE pos = size;
76         pos += offset;
77
78         if (!pos.IsValid() || pos.ValueOrDie() > m_pFile->GetSize()) {
79             return FALSE;
80         }
81
82         m_nOffset = offset, m_nSize = size;
83         m_bUseRange = TRUE;
84         m_pFile->SetPosition(m_nOffset);
85         return TRUE;
86     }
87     virtual void                                ClearRange() FX_OVERRIDE
88     {
89         m_bUseRange = FALSE;
90     }
91     virtual FX_BOOL                             ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) FX_OVERRIDE
92     {
93         if (m_bUseRange && offset < 0) {
94             return FALSE;
95         }
96         FX_SAFE_FILESIZE pos = offset;
97
98         if (m_bUseRange) {
99             pos += m_nOffset;
100             if (!pos.IsValid() || pos.ValueOrDie() > (size_t)GetSize()) {
101                 return FALSE;
102             }
103         }
104         return (FX_BOOL)m_pFile->ReadPos(buffer, size, pos.ValueOrDie());
105     }
106     virtual size_t                              ReadBlock(void* buffer, size_t size) FX_OVERRIDE
107     {
108         if (m_bUseRange) {
109             FX_FILESIZE availSize = m_nOffset + m_nSize - m_pFile->GetPosition();
110             if ((size_t)availSize < size) {
111                 size -= size - (size_t)availSize;
112             }
113         }
114         return m_pFile->Read(buffer, size);
115     }
116     virtual     FX_BOOL                         WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) FX_OVERRIDE
117     {
118         if (m_bUseRange) {
119             offset += m_nOffset;
120         }
121         return (FX_BOOL)m_pFile->WritePos(buffer, size, offset);
122     }
123     virtual FX_BOOL                             Flush()  FX_OVERRIDE
124     {
125         return m_pFile->Flush();
126     }
127     IFXCRT_FileAccess*  m_pFile;
128     FX_DWORD                    m_dwCount;
129     FX_BOOL                             m_bUseRange;
130     FX_FILESIZE                 m_nOffset;
131     FX_FILESIZE                 m_nSize;
132 };
133 #define FX_MEMSTREAM_BlockSize          (64 * 1024)
134 #define FX_MEMSTREAM_Consecutive        0x01
135 #define FX_MEMSTREAM_TakeOver           0x02
136 class CFX_MemoryStream FX_FINAL : public IFX_MemoryStream
137 {
138 public:
139     CFX_MemoryStream(FX_BOOL bConsecutive)
140         : m_dwCount(1)
141         , m_nTotalSize(0)
142         , m_nCurSize(0)
143         , m_nCurPos(0)
144         , m_nGrowSize(FX_MEMSTREAM_BlockSize)
145         , m_bUseRange(FALSE)
146     {
147         m_dwFlags = FX_MEMSTREAM_TakeOver | (bConsecutive ? FX_MEMSTREAM_Consecutive : 0);
148     }
149     CFX_MemoryStream(FX_LPBYTE pBuffer, size_t nSize, FX_BOOL bTakeOver)
150         : m_dwCount(1)
151         , m_nTotalSize(nSize)
152         , m_nCurSize(nSize)
153         , m_nCurPos(0)
154         , m_nGrowSize(FX_MEMSTREAM_BlockSize)
155         , m_bUseRange(FALSE)
156     {
157         m_Blocks.Add(pBuffer);
158         m_dwFlags = FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
159     }
160     ~CFX_MemoryStream()
161     {
162         if (m_dwFlags & FX_MEMSTREAM_TakeOver) {
163             for (FX_INT32 i = 0; i < m_Blocks.GetSize(); i++) {
164                 FX_Free((FX_LPBYTE)m_Blocks[i]);
165             }
166         }
167         m_Blocks.RemoveAll();
168     }
169     virtual IFX_FileStream*             Retain()  FX_OVERRIDE
170     {
171         m_dwCount ++;
172         return this;
173     }
174     virtual void                                Release()  FX_OVERRIDE
175     {
176         FX_DWORD nCount = -- m_dwCount;
177         if (nCount) {
178             return;
179         }
180         delete this;
181     }
182     virtual FX_FILESIZE                 GetSize()  FX_OVERRIDE
183     {
184         return m_bUseRange ? (FX_FILESIZE) m_nSize : (FX_FILESIZE)m_nCurSize;
185     }
186     virtual FX_BOOL                             IsEOF()  FX_OVERRIDE
187     {
188         return m_nCurPos >= (size_t)GetSize();
189     }
190     virtual FX_FILESIZE                 GetPosition()  FX_OVERRIDE
191     {
192         FX_FILESIZE pos = (FX_FILESIZE)m_nCurPos;
193         if (m_bUseRange) {
194             pos -= (FX_FILESIZE)m_nOffset;
195         }
196         return pos;
197     }
198     virtual FX_BOOL                             SetRange(FX_FILESIZE offset, FX_FILESIZE size)  FX_OVERRIDE
199     {
200         if (offset < 0 || size < 0) {
201             return FALSE;
202         }
203         FX_SAFE_FILESIZE range = size;
204         range += offset;
205         if (!range.IsValid() || range.ValueOrDie() > m_nCurSize) {
206             return FALSE;
207         }
208         
209         m_nOffset = (size_t)offset, m_nSize = (size_t)size;
210         m_bUseRange = TRUE;
211         m_nCurPos = m_nOffset;
212         return TRUE;
213     }
214     virtual void                                ClearRange()  FX_OVERRIDE
215     {
216         m_bUseRange = FALSE;
217     }
218     virtual FX_BOOL                             ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)  FX_OVERRIDE
219     {
220         if (!buffer || !size) {
221             return FALSE;
222         }
223
224         FX_SAFE_FILESIZE safeOffset = offset;
225         if (m_bUseRange) {
226             safeOffset += m_nOffset;
227         }
228          
229         if (!safeOffset.IsValid()) {
230             return FALSE;
231         }
232
233         offset = safeOffset.ValueOrDie();
234
235         FX_SAFE_SIZE_T newPos = size;
236         newPos += offset;
237         if (!newPos.IsValid() || newPos.ValueOrDefault(0) == 0 || newPos.ValueOrDie() > m_nCurSize) {
238             return FALSE;
239         }
240
241         m_nCurPos = newPos.ValueOrDie();
242         if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
243             FXSYS_memcpy32(buffer, (FX_LPBYTE)m_Blocks[0] + (size_t)offset, size);
244             return TRUE;
245         }
246         size_t nStartBlock = (size_t)offset / m_nGrowSize;
247         offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
248         while (size) {
249             size_t nRead = m_nGrowSize - (size_t)offset;
250             if (nRead > size) {
251                 nRead = size;
252             }
253             FXSYS_memcpy32(buffer, (FX_LPBYTE)m_Blocks[(int)nStartBlock] + (size_t)offset, nRead);
254             buffer = ((FX_LPBYTE)buffer) + nRead;
255             size -= nRead;
256             nStartBlock ++;
257             offset = 0;
258         }
259         return TRUE;
260     }
261     virtual size_t                              ReadBlock(void* buffer, size_t size)  FX_OVERRIDE
262     {
263         if (m_nCurPos >= m_nCurSize) {
264             return 0;
265         }
266         if (m_bUseRange) {
267             size_t availSize = m_nOffset + m_nSize - m_nCurPos;
268             if (availSize < size) {
269                 size -= size - (size_t)availSize;
270             }
271         }
272         size_t nRead = FX_MIN(size, m_nCurSize - m_nCurPos);
273         if (!ReadBlock(buffer, (FX_INT32)m_nCurPos, nRead)) {
274             return 0;
275         }
276         return nRead;
277     }
278     virtual     FX_BOOL                         WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size)  FX_OVERRIDE
279     {
280         if (!buffer || !size) {
281             return FALSE;
282         }
283         if (m_bUseRange) {
284             offset += (FX_FILESIZE)m_nOffset;
285         }
286         if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
287             FX_SAFE_SIZE_T newPos = size; 
288             newPos += offset;
289             if (!newPos.IsValid())
290                 return FALSE;
291
292             m_nCurPos = newPos.ValueOrDie();
293             if (m_nCurPos > m_nTotalSize) {
294                 m_nTotalSize = (m_nCurPos + m_nGrowSize - 1) / m_nGrowSize * m_nGrowSize;
295                 if (m_Blocks.GetSize() < 1) {
296                     void* block = FX_Alloc(FX_BYTE, m_nTotalSize);
297                     m_Blocks.Add(block);
298                 } else {
299                     m_Blocks[0] = FX_Realloc(FX_BYTE, m_Blocks[0], m_nTotalSize);
300                 }
301                 if (!m_Blocks[0]) {
302                     m_Blocks.RemoveAll();
303                     return FALSE;
304                 }
305             }
306             FXSYS_memcpy32((FX_LPBYTE)m_Blocks[0] + (size_t)offset, buffer, size);
307             if (m_nCurSize < m_nCurPos) {
308                 m_nCurSize = m_nCurPos;
309             }
310             return TRUE;
311         }
312
313         FX_SAFE_SIZE_T newPos = size;
314         newPos += offset;
315         if (!newPos.IsValid()) {
316             return FALSE;
317         }
318
319         if (!ExpandBlocks(newPos.ValueOrDie())) {
320             return FALSE;
321         }
322         m_nCurPos = newPos.ValueOrDie();
323         size_t nStartBlock = (size_t)offset / m_nGrowSize;
324         offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
325         while (size) {
326             size_t nWrite = m_nGrowSize - (size_t)offset;
327             if (nWrite > size) {
328                 nWrite = size;
329             }
330             FXSYS_memcpy32((FX_LPBYTE)m_Blocks[(int)nStartBlock] + (size_t)offset, buffer, nWrite);
331             buffer = ((FX_LPBYTE)buffer) + nWrite;
332             size -= nWrite;
333             nStartBlock ++;
334             offset = 0;
335         }
336         return TRUE;
337     }
338     virtual FX_BOOL                             Flush()  FX_OVERRIDE
339     {
340         return TRUE;
341     }
342     virtual FX_BOOL                             IsConsecutive() const  FX_OVERRIDE
343     {
344         return m_dwFlags & FX_MEMSTREAM_Consecutive;
345     }
346     virtual void                                EstimateSize(size_t nInitSize, size_t nGrowSize)  FX_OVERRIDE
347     {
348         if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
349             if (m_Blocks.GetSize() < 1) {
350                 FX_LPBYTE pBlock = FX_Alloc(FX_BYTE, FX_MAX(nInitSize, 4096));
351                 if (pBlock) {
352                     m_Blocks.Add(pBlock);
353                 }
354             }
355             m_nGrowSize = FX_MAX(nGrowSize, 4096);
356         } else if (m_Blocks.GetSize() < 1) {
357             m_nGrowSize = FX_MAX(nGrowSize, 4096);
358         }
359     }
360     virtual FX_LPBYTE                   GetBuffer() const  FX_OVERRIDE
361     {
362         return m_Blocks.GetSize() ? (FX_LPBYTE)m_Blocks[0] : NULL;
363     }
364     virtual void                                AttachBuffer(FX_LPBYTE pBuffer, size_t nSize, FX_BOOL bTakeOver = FALSE)  FX_OVERRIDE
365     {
366         if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
367             return;
368         }
369         m_Blocks.RemoveAll();
370         m_Blocks.Add(pBuffer);
371         m_nTotalSize = m_nCurSize = nSize;
372         m_nCurPos = 0;
373         m_dwFlags = FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
374         ClearRange();
375     }
376     virtual void                                DetachBuffer()  FX_OVERRIDE
377     {
378         if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
379             return;
380         }
381         m_Blocks.RemoveAll();
382         m_nTotalSize = m_nCurSize = m_nCurPos = 0;
383         m_dwFlags = FX_MEMSTREAM_TakeOver;
384         ClearRange();
385     }
386 protected:
387     CFX_PtrArray        m_Blocks;
388     FX_DWORD            m_dwCount;
389     size_t                      m_nTotalSize;
390     size_t                      m_nCurSize;
391     size_t                      m_nCurPos;
392     size_t                      m_nGrowSize;
393     FX_DWORD            m_dwFlags;
394     FX_BOOL                     m_bUseRange;
395     size_t                      m_nOffset;
396     size_t                      m_nSize;
397     FX_BOOL     ExpandBlocks(size_t size)
398     {
399         if (m_nCurSize < size) {
400             m_nCurSize = size;
401         }
402         if (size <= m_nTotalSize) {
403             return TRUE;
404         }
405         FX_INT32 iCount = m_Blocks.GetSize();
406         size = (size - m_nTotalSize + m_nGrowSize - 1) / m_nGrowSize;
407         m_Blocks.SetSize(m_Blocks.GetSize() + (FX_INT32)size);
408         while (size --) {
409             FX_LPBYTE pBlock = FX_Alloc(FX_BYTE, m_nGrowSize);
410             if (!pBlock) {
411                 return FALSE;
412             }
413             m_Blocks.SetAt(iCount ++, pBlock);
414             m_nTotalSize += m_nGrowSize;
415         }
416         return TRUE;
417     }
418 };
419 #ifdef __cplusplus
420 extern "C" {
421 #endif
422 #define MT_N                    848
423 #define MT_M                    456
424 #define MT_Matrix_A             0x9908b0df
425 #define MT_Upper_Mask   0x80000000
426 #define MT_Lower_Mask   0x7fffffff
427 typedef struct _FX_MTRANDOMCONTEXT {
428     _FX_MTRANDOMCONTEXT()
429     {
430         mti = MT_N + 1;
431         bHaveSeed = FALSE;
432     }
433     FX_DWORD mti;
434     FX_BOOL      bHaveSeed;
435     FX_DWORD mt[MT_N];
436 } FX_MTRANDOMCONTEXT, * FX_LPMTRANDOMCONTEXT;
437 typedef FX_MTRANDOMCONTEXT const * FX_LPCMTRANDOMCONTEXT;
438 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
439 FX_BOOL FX_GenerateCryptoRandom(FX_LPDWORD pBuffer, FX_INT32 iCount);
440 #endif
441 #ifdef __cplusplus
442 }
443 #endif
444 #endif