diff options
-rw-r--r-- | vcl/source/font/fontcharmap.cxx | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/vcl/source/font/fontcharmap.cxx b/vcl/source/font/fontcharmap.cxx index a375f98fa14f..f9aa5ded6963 100644 --- a/vcl/source/font/fontcharmap.cxx +++ b/vcl/source/font/fontcharmap.cxx @@ -20,6 +20,7 @@ #include <impfontcharmap.hxx> #include <sal/log.hxx> +#include <algorithm> #include <vector> #include <set> @@ -149,6 +150,10 @@ bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult ) continue; int nTmpOffset = GetUInt( p+4 ); + + if (nTmpOffset > nLength - 2 || nTmpOffset < 0) + continue; + int nTmpFormat = GetUShort( pCmap + nTmpOffset ); if( nTmpFormat == 12 ) // 32bit code -> glyph map format nValue += 3; @@ -178,12 +183,29 @@ bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult ) { int nSegCountX2 = GetUShort( pCmap + nOffset + 6 ); nRangeCount = nSegCountX2/2 - 1; - pCodePairs = new sal_UCS4[ nRangeCount * 2 ]; - pStartGlyphs = new int[ nRangeCount ]; + if (nRangeCount < 0) + { + SAL_WARN("vcl.gdi", "negative RangeCount"); + nRangeCount = 0; + } + const unsigned char* pLimitBase = pCmap + nOffset + 14; const unsigned char* pBeginBase = pLimitBase + nSegCountX2 + 2; const unsigned char* pDeltaBase = pBeginBase + nSegCountX2; const unsigned char* pOffsetBase = pDeltaBase + nSegCountX2; + + const int nOffsetBaseStart = pOffsetBase - pCmap; + const int nRemainingLen = nLength - nOffsetBaseStart; + const int nMaxPossibleRangeOffsets = nRemainingLen / 2; + if (nRangeCount > nMaxPossibleRangeOffsets) + { + SAL_WARN("vcl.gdi", "more range offsets requested then space available"); + nRangeCount = std::max(0, nMaxPossibleRangeOffsets); + } + + pCodePairs = new sal_UCS4[ nRangeCount * 2 ]; + pStartGlyphs = new int[ nRangeCount ]; + sal_UCS4* pCP = pCodePairs; for( int i = 0; i < nRangeCount; ++i ) { @@ -243,7 +265,7 @@ bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult ) if (nRangeCount > nMaxPossiblePairs) { SAL_WARN("vcl.gdi", "more code pairs requested then space available"); - nRangeCount = nMaxPossiblePairs; + nRangeCount = std::max(0, nMaxPossiblePairs); } pCodePairs = new sal_UCS4[ nRangeCount * 2 ]; @@ -317,7 +339,9 @@ bool ParseCMAP( const unsigned char* pCmap, int nLength, CmapResult& rResult ) { sal_UCS4 cMin = *(pCP++); sal_UCS4 cEnd = *(pCP++); - while( cMin < cEnd ) + // ofz#25868 the conversion only makes sense with + // input codepoints in 0..SAL_MAX_UINT16 range + while (cMin < cEnd && cMin <= SAL_MAX_UINT16) { int j = 0; for(; (cMin < cEnd) && (j < NINSIZE); ++cMin ) |