diff --git a/DesktopEditor/raster/Metafile/Common/MetaFileUtils.h b/DesktopEditor/raster/Metafile/Common/MetaFileUtils.h index ae76ba586d..7767bd9c97 100644 --- a/DesktopEditor/raster/Metafile/Common/MetaFileUtils.h +++ b/DesktopEditor/raster/Metafile/Common/MetaFileUtils.h @@ -93,7 +93,7 @@ namespace MetaFile { public: - CDataStream() : pBuffer(NULL) + CDataStream() : pBuffer(NULL), pBufferEnd(NULL), pEnd(NULL), pCur(NULL) { } @@ -103,10 +103,25 @@ namespace MetaFile void SetStream(BYTE* pBuf, unsigned int unSize) { - pBuffer = pBuf; - pCur = pBuf; - pEnd = pBuf + unSize; - }; + pBuffer = pBuf; + pCur = pBuf; + pBufferEnd = pBuf + unSize; + pEnd = pBufferEnd; + } + + void SetCurrentBlockSize(unsigned int unSize) + { + if (pCur + unSize >= pBufferEnd) + pEnd = pBufferEnd; + else + pEnd = pCur + unSize; + } + + void ClearCurrentBlockSize() + { + pEnd = pBufferEnd; + } + BYTE* GetCurPtr() { return pCur; @@ -120,7 +135,7 @@ namespace MetaFile unsigned char unResult = pCur[0]; pCur++; return unResult; - }; + } unsigned short ReadUShort() { if (pCur + 1 >= pEnd) @@ -129,7 +144,7 @@ namespace MetaFile unsigned short ushResult = (pCur[0]) | ((pCur[1]) << 8); pCur += 2; return ushResult; - }; + } unsigned int ReadULong() { if (pCur + 3 >= pEnd) @@ -138,7 +153,7 @@ namespace MetaFile unsigned int unResult = (unsigned int)((pCur[0] << 0) | ((pCur[1]) << 8) | ((pCur[2]) << 16) | ((pCur[3]) << 24)); pCur += 4; return unResult; - }; + } double ReadDouble() { if (pCur + 3 >= pEnd) @@ -159,19 +174,19 @@ namespace MetaFile int lFracValue = (int)(pCur[3]); pCur += 4; return (double)(lIntValue + (lFracValue / 16.0)); - }; + } char ReadChar() { return (char)ReadUChar(); - }; + } short ReadShort() { return (short)ReadUShort(); - }; + } int ReadLong() { return (int)ReadULong(); - }; + } void ReadBytes(unsigned char* pBuffer, unsigned int ulSize) { size_t ulRemainSize = (pEnd - pCur); @@ -181,7 +196,7 @@ namespace MetaFile { pBuffer[ulIndex] = ReadChar(); } - }; + } void ReadBytes(unsigned short* pBuffer, unsigned int ulSize) { size_t ulRemainSize = (pEnd - pCur) / 2; @@ -1047,7 +1062,7 @@ namespace MetaFile bool IsEof() const { - if (pCur >= pEnd) + if (pCur >= pBufferEnd) return true; return false; @@ -1060,7 +1075,10 @@ namespace MetaFile void Skip(unsigned int ulSkip) { - pCur += ulSkip; + if (pCur + ulSkip >= pEnd) + pCur = pEnd; + else + pCur += ulSkip; } void SeekBack(unsigned int ulSkipBack) @@ -1071,6 +1089,7 @@ namespace MetaFile void SeekToStart() { pCur = pBuffer; + ClearCurrentBlockSize(); } unsigned int CanRead() @@ -1085,21 +1104,31 @@ namespace MetaFile *this >> oText; // Читаем OutputString - const unsigned int unCharsCount = oText.unChars; - int nSkip = oText.unOffString - (unOffset + 40); // 40 - размер структуры TEmfEmrText - Skip(nSkip); - T* pString = new T[unCharsCount + 1]; + oText.unChars = std::min(oText.unChars, (UINT)(CanRead() / sizeof(T))); + + if (0 == oText.unChars) + return; + + if (oText.unOffString - 40 > unOffset) + Skip(oText.unOffString - (unOffset + 40)); // 40 - размер структуры TEmfEmrText + + T* pString = new T[oText.unChars + 1]; if (pString) { - pString[unCharsCount] = 0x00; - ReadBytes(pString, unCharsCount); + pString[oText.unChars] = 0x00; + ReadBytes(pString, oText.unChars); oText.pOutputString = pString; } // Читаем OutputDx - nSkip = oText.unOffDx - oText.unOffString - 2 * unCharsCount; - Skip(nSkip); - const unsigned int unDxCount = oText.unOptions & ETO_PDY ? 2 * unCharsCount : unCharsCount; + if (oText.unChars < (UINT32_MAX / 2) && (oText.unOffDx > oText.unOffString) && (oText.unOffDx - oText.unOffString > 2 * oText.unChars)) + Skip(oText.unOffDx - oText.unOffString - 2 * oText.unChars); + + const unsigned int unDxCount = (oText.unOptions & ETO_PDY ? 2 * oText.unChars : oText.unChars); + + if ((CanRead() / 4) < unDxCount || 0 == unDxCount) + return; + unsigned int* pDx = new unsigned int[unDxCount]; if (pDx) { @@ -1116,6 +1145,7 @@ namespace MetaFile private: BYTE *pBuffer; + BYTE *pBufferEnd; BYTE *pCur; BYTE *pEnd; }; diff --git a/DesktopEditor/raster/Metafile/Emf/EmfParser/CEmfParser.cpp b/DesktopEditor/raster/Metafile/Emf/EmfParser/CEmfParser.cpp index 078a3bdac2..f46fecb4b5 100644 --- a/DesktopEditor/raster/Metafile/Emf/EmfParser/CEmfParser.cpp +++ b/DesktopEditor/raster/Metafile/Emf/EmfParser/CEmfParser.cpp @@ -63,6 +63,8 @@ namespace MetaFile m_ulRecordPos = m_oStream.Tell(); m_ulRecordSize = ulSize - 8; + m_oStream.SetCurrentBlockSize(m_ulRecordSize); + if (ulType < EMR_MIN || ulType > EMR_MAX) { if (ENHMETA_SIGNATURE != m_oHeader.ulSignature || 0x00010000 != m_oHeader.ulVersion) @@ -213,6 +215,8 @@ namespace MetaFile m_oStream.Skip(need_skip); ulRecordIndex++; + m_oStream.ClearCurrentBlockSize(); + } while (!CheckError()); if (!CheckError()) diff --git a/DesktopEditor/raster/Metafile/Emf/EmfParser/CEmfPlusParser.cpp b/DesktopEditor/raster/Metafile/Emf/EmfParser/CEmfPlusParser.cpp index d0ef37afbb..542837ff1f 100644 --- a/DesktopEditor/raster/Metafile/Emf/EmfParser/CEmfPlusParser.cpp +++ b/DesktopEditor/raster/Metafile/Emf/EmfParser/CEmfPlusParser.cpp @@ -234,6 +234,8 @@ namespace MetaFile m_oStream >> unSize; m_oStream >> m_ulRecordSize; + m_oStream.SetCurrentBlockSize(m_ulRecordSize); + unsigned int unRecordPos = m_oStream.Tell(); LOGGING(ActionNamesEmfPlus[unShType] << L" DataSize = " << m_ulRecordSize) @@ -318,6 +320,7 @@ namespace MetaFile LOGGING(L"Skip: " << nNeedSkip) + m_oStream.ClearCurrentBlockSize(); m_ulRecordSize = 0; }while(m_oStream.CanRead() >= 12 && !m_bEof); diff --git a/DesktopEditor/raster/Metafile/Wmf/WmfParser/CWmfParser.cpp b/DesktopEditor/raster/Metafile/Wmf/WmfParser/CWmfParser.cpp index 33803d513a..34ec3fa88c 100644 --- a/DesktopEditor/raster/Metafile/Wmf/WmfParser/CWmfParser.cpp +++ b/DesktopEditor/raster/Metafile/Wmf/WmfParser/CWmfParser.cpp @@ -52,6 +52,8 @@ namespace MetaFile m_unRecordSize = unSize * 2; // Размер указан в WORD + m_oStream.SetCurrentBlockSize(m_unRecordSize); + switch (ushType) { //----------------------------------------------------------- @@ -161,6 +163,7 @@ namespace MetaFile // Пропускаем лишние байты, которые могли быть в записи int need_skip = m_unRecordSize - (m_oStream.Tell() - m_unRecordPos); m_oStream.Skip(need_skip); + m_oStream.ClearCurrentBlockSize(); }; if (!m_bEof)