Fix potential UAF in ConcatInPlace.
[pdfium.git] / core / src / fxcrt / extension.h
index a2d0a14..dbee7e6 100644 (file)
@@ -6,6 +6,9 @@
 
 #ifndef _FXCRT_EXTENSION_IMP_
 #define _FXCRT_EXTENSION_IMP_
+
+#include "fx_safe_types.h"
+
 class IFXCRT_FileAccess
 {
 public:
@@ -25,7 +28,7 @@ public:
     virtual FX_BOOL            Truncate(FX_FILESIZE szFile) = 0;
 };
 IFXCRT_FileAccess*     FXCRT_FileAccess_Create();
-class CFX_CRTFileStream FX_FINAL : public IFX_FileStream, public CFX_Object
+class CFX_CRTFileStream FX_FINAL : public IFX_FileStream
 {
 public:
     CFX_CRTFileStream(IFXCRT_FileAccess* pFA) : m_pFile(pFA), m_dwCount(1), m_bUseRange(FALSE), m_nOffset(0), m_nSize(0) {}
@@ -35,27 +38,27 @@ public:
             m_pFile->Release();
         }
     }
-    virtual IFX_FileStream*            Retain()
+    virtual IFX_FileStream*            Retain() FX_OVERRIDE
     {
         m_dwCount ++;
         return this;
     }
-    virtual void                               Release()
+    virtual void                               Release() FX_OVERRIDE
     {
         FX_DWORD nCount = -- m_dwCount;
         if (!nCount) {
             delete this;
         }
     }
-    virtual FX_FILESIZE                        GetSize()
+    virtual FX_FILESIZE                        GetSize() FX_OVERRIDE
     {
         return m_bUseRange ? m_nSize : m_pFile->GetSize();
     }
-    virtual FX_BOOL                            IsEOF()
+    virtual FX_BOOL                            IsEOF() FX_OVERRIDE
     {
         return GetPosition() >= GetSize();
     }
-    virtual FX_FILESIZE                        GetPosition()
+    virtual FX_FILESIZE                        GetPosition() FX_OVERRIDE
     {
         FX_FILESIZE pos = m_pFile->GetPosition();
         if (m_bUseRange) {
@@ -63,31 +66,44 @@ public:
         }
         return pos;
     }
-    virtual FX_BOOL                            SetRange(FX_FILESIZE offset, FX_FILESIZE size)
+    virtual FX_BOOL                            SetRange(FX_FILESIZE offset, FX_FILESIZE size) FX_OVERRIDE
     {
-        if (offset < 0 || offset + size > m_pFile->GetSize()) {
+        if (offset < 0 || size < 0) {
             return FALSE;
         }
+     
+        FX_SAFE_FILESIZE pos = size;
+        pos += offset;
+
+        if (!pos.IsValid() || pos.ValueOrDie() > m_pFile->GetSize()) {
+            return FALSE;
+        }
+
         m_nOffset = offset, m_nSize = size;
         m_bUseRange = TRUE;
         m_pFile->SetPosition(m_nOffset);
         return TRUE;
     }
-    virtual void                               ClearRange()
+    virtual void                               ClearRange() FX_OVERRIDE
     {
         m_bUseRange = FALSE;
     }
-    virtual FX_BOOL                            ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)
+    virtual FX_BOOL                            ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) FX_OVERRIDE
     {
+        if (m_bUseRange && offset < 0) {
+            return FALSE;
+        }
+        FX_SAFE_FILESIZE pos = offset;
+
         if (m_bUseRange) {
-            if (offset + size > (size_t)GetSize()) {
+            pos += m_nOffset;
+            if (!pos.IsValid() || pos.ValueOrDie() > (size_t)GetSize()) {
                 return FALSE;
             }
-            offset += m_nOffset;
         }
-        return (FX_BOOL)m_pFile->ReadPos(buffer, size, offset);
+        return (FX_BOOL)m_pFile->ReadPos(buffer, size, pos.ValueOrDie());
     }
-    virtual size_t                             ReadBlock(void* buffer, size_t size)
+    virtual size_t                             ReadBlock(void* buffer, size_t size) FX_OVERRIDE
     {
         if (m_bUseRange) {
             FX_FILESIZE availSize = m_nOffset + m_nSize - m_pFile->GetPosition();
@@ -97,14 +113,14 @@ public:
         }
         return m_pFile->Read(buffer, size);
     }
-    virtual    FX_BOOL                         WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size)
+    virtual    FX_BOOL                         WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) FX_OVERRIDE
     {
         if (m_bUseRange) {
             offset += m_nOffset;
         }
         return (FX_BOOL)m_pFile->WritePos(buffer, size, offset);
     }
-    virtual FX_BOOL                            Flush()
+    virtual FX_BOOL                            Flush()  FX_OVERRIDE
     {
         return m_pFile->Flush();
     }
@@ -117,7 +133,7 @@ public:
 #define FX_MEMSTREAM_BlockSize         (64 * 1024)
 #define FX_MEMSTREAM_Consecutive       0x01
 #define FX_MEMSTREAM_TakeOver          0x02
-class CFX_MemoryStream FX_FINAL : public IFX_MemoryStream, public CFX_Object
+class CFX_MemoryStream FX_FINAL : public IFX_MemoryStream
 {
 public:
     CFX_MemoryStream(FX_BOOL bConsecutive)
@@ -150,12 +166,12 @@ public:
         }
         m_Blocks.RemoveAll();
     }
-    virtual IFX_FileStream*            Retain()
+    virtual IFX_FileStream*            Retain()  FX_OVERRIDE
     {
         m_dwCount ++;
         return this;
     }
-    virtual void                               Release()
+    virtual void                               Release()  FX_OVERRIDE
     {
         FX_DWORD nCount = -- m_dwCount;
         if (nCount) {
@@ -163,15 +179,15 @@ public:
         }
         delete this;
     }
-    virtual FX_FILESIZE                        GetSize()
+    virtual FX_FILESIZE                        GetSize()  FX_OVERRIDE
     {
         return m_bUseRange ? (FX_FILESIZE) m_nSize : (FX_FILESIZE)m_nCurSize;
     }
-    virtual FX_BOOL                            IsEOF()
+    virtual FX_BOOL                            IsEOF()  FX_OVERRIDE
     {
         return m_nCurPos >= (size_t)GetSize();
     }
-    virtual FX_FILESIZE                        GetPosition()
+    virtual FX_FILESIZE                        GetPosition()  FX_OVERRIDE
     {
         FX_FILESIZE pos = (FX_FILESIZE)m_nCurPos;
         if (m_bUseRange) {
@@ -179,32 +195,50 @@ public:
         }
         return pos;
     }
-    virtual FX_BOOL                            SetRange(FX_FILESIZE offset, FX_FILESIZE size)
+    virtual FX_BOOL                            SetRange(FX_FILESIZE offset, FX_FILESIZE size)  FX_OVERRIDE
     {
-        if (offset < 0 || (size_t)(offset + size) > m_nCurSize) {
+        if (offset < 0 || size < 0) {
             return FALSE;
         }
+        FX_SAFE_FILESIZE range = size;
+        range += offset;
+        if (!range.IsValid() || range.ValueOrDie() > m_nCurSize) {
+            return FALSE;
+        }
+        
         m_nOffset = (size_t)offset, m_nSize = (size_t)size;
         m_bUseRange = TRUE;
         m_nCurPos = m_nOffset;
         return TRUE;
     }
-    virtual void                               ClearRange()
+    virtual void                               ClearRange()  FX_OVERRIDE
     {
         m_bUseRange = FALSE;
     }
-    virtual FX_BOOL                            ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)
+    virtual FX_BOOL                            ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)  FX_OVERRIDE
     {
         if (!buffer || !size) {
             return FALSE;
         }
+
+        FX_SAFE_FILESIZE safeOffset = offset;
         if (m_bUseRange) {
-            offset += (FX_FILESIZE)m_nOffset;
+            safeOffset += m_nOffset;
+        }
+         
+        if (!safeOffset.IsValid()) {
+            return FALSE;
         }
-        if ((size_t)offset + size > m_nCurSize) {
+
+        offset = safeOffset.ValueOrDie();
+
+        FX_SAFE_SIZE_T newPos = size;
+        newPos += offset;
+        if (!newPos.IsValid() || newPos.ValueOrDefault(0) == 0 || newPos.ValueOrDie() > m_nCurSize) {
             return FALSE;
         }
-        m_nCurPos = (size_t)offset + size;
+
+        m_nCurPos = newPos.ValueOrDie();
         if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
             FXSYS_memcpy32(buffer, (FX_LPBYTE)m_Blocks[0] + (size_t)offset, size);
             return TRUE;
@@ -224,7 +258,7 @@ public:
         }
         return TRUE;
     }
-    virtual size_t                             ReadBlock(void* buffer, size_t size)
+    virtual size_t                             ReadBlock(void* buffer, size_t size)  FX_OVERRIDE
     {
         if (m_nCurPos >= m_nCurSize) {
             return 0;
@@ -241,7 +275,7 @@ public:
         }
         return nRead;
     }
-    virtual    FX_BOOL                         WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size)
+    virtual    FX_BOOL                         WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size)  FX_OVERRIDE
     {
         if (!buffer || !size) {
             return FALSE;
@@ -250,7 +284,12 @@ public:
             offset += (FX_FILESIZE)m_nOffset;
         }
         if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
-            m_nCurPos = (size_t)offset + size;
+            FX_SAFE_SIZE_T newPos = size; 
+            newPos += offset;
+            if (!newPos.IsValid())
+                return FALSE;
+
+            m_nCurPos = newPos.ValueOrDie();
             if (m_nCurPos > m_nTotalSize) {
                 m_nTotalSize = (m_nCurPos + m_nGrowSize - 1) / m_nGrowSize * m_nGrowSize;
                 if (m_Blocks.GetSize() < 1) {
@@ -270,10 +309,17 @@ public:
             }
             return TRUE;
         }
-        if (!ExpandBlocks((size_t)offset + size)) {
+
+        FX_SAFE_SIZE_T newPos = size;
+        newPos += offset;
+        if (!newPos.IsValid()) {
+            return FALSE;
+        }
+
+        if (!ExpandBlocks(newPos.ValueOrDie())) {
             return FALSE;
         }
-        m_nCurPos = (size_t)offset + size;
+        m_nCurPos = newPos.ValueOrDie();
         size_t nStartBlock = (size_t)offset / m_nGrowSize;
         offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
         while (size) {
@@ -289,15 +335,15 @@ public:
         }
         return TRUE;
     }
-    virtual FX_BOOL                            Flush()
+    virtual FX_BOOL                            Flush()  FX_OVERRIDE
     {
         return TRUE;
     }
-    virtual FX_BOOL                            IsConsecutive() const
+    virtual FX_BOOL                            IsConsecutive() const  FX_OVERRIDE
     {
         return m_dwFlags & FX_MEMSTREAM_Consecutive;
     }
-    virtual void                               EstimateSize(size_t nInitSize, size_t nGrowSize)
+    virtual void                               EstimateSize(size_t nInitSize, size_t nGrowSize)  FX_OVERRIDE
     {
         if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
             if (m_Blocks.GetSize() < 1) {
@@ -311,11 +357,11 @@ public:
             m_nGrowSize = FX_MAX(nGrowSize, 4096);
         }
     }
-    virtual FX_LPBYTE                  GetBuffer() const
+    virtual FX_LPBYTE                  GetBuffer() const  FX_OVERRIDE
     {
         return m_Blocks.GetSize() ? (FX_LPBYTE)m_Blocks[0] : NULL;
     }
-    virtual void                               AttachBuffer(FX_LPBYTE pBuffer, size_t nSize, FX_BOOL bTakeOver = FALSE)
+    virtual void                               AttachBuffer(FX_LPBYTE pBuffer, size_t nSize, FX_BOOL bTakeOver = FALSE)  FX_OVERRIDE
     {
         if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
             return;
@@ -327,7 +373,7 @@ public:
         m_dwFlags = FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
         ClearRange();
     }
-    virtual void                               DetachBuffer()
+    virtual void                               DetachBuffer()  FX_OVERRIDE
     {
         if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
             return;