diff options
Diffstat (limited to 'vcl/source/fontsubset/sft.cxx')
-rw-r--r-- | vcl/source/fontsubset/sft.cxx | 95 |
1 files changed, 71 insertions, 24 deletions
diff --git a/vcl/source/fontsubset/sft.cxx b/vcl/source/fontsubset/sft.cxx index 4a44fd316bee..365b9401b95e 100644 --- a/vcl/source/fontsubset/sft.cxx +++ b/vcl/source/fontsubset/sft.cxx @@ -38,7 +38,7 @@ #include "xlat.hxx" #include <rtl/crc.h> #include <rtl/ustring.hxx> - +#include <o3tl/safeint.hxx> #include <osl/endian.h> #include <algorithm> @@ -1320,6 +1320,13 @@ static void FindCmap(TrueTypeFont *ttf) } if (ttf->cmapType != CMAP_NOT_USABLE) { + if( (ttf->cmap - ttf->ptr + 2U) > static_cast<sal_uInt32>(ttf->fsize) ) { + ttf->cmapType = CMAP_NOT_USABLE; + ttf->cmap = nullptr; + } + } + + if (ttf->cmapType != CMAP_NOT_USABLE) { switch (GetUInt16(ttf->cmap, 0)) { case 0: ttf->mapper = getGlyph0; break; case 2: ttf->mapper = getGlyph2; break; @@ -1443,10 +1450,41 @@ int OpenTTFontBuffer(const void* pBuffer, sal_uInt32 nLen, sal_uInt32 facenum, T return doOpenTTFont( facenum, *ttf ); } +namespace { + +bool withinBounds(sal_uInt32 tdoffset, sal_uInt32 moreoffset, sal_uInt32 len, sal_uInt32 available) +{ + sal_uInt32 result; + if (o3tl::checked_add(tdoffset, moreoffset, result)) + return false; + if (o3tl::checked_add(result, len, result)) + return false; + return result <= available; +} + +class TTFontCloser +{ + TrueTypeFont* m_font; +public: + TTFontCloser(TrueTypeFont* t) + : m_font(t) + { + } + void clear() { m_font = nullptr; } + ~TTFontCloser() + { + if (m_font) + CloseTTFont(m_font); + } +}; + +} + static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) { + TTFontCloser aCloseGuard(t); + if (t->fsize < 4) { - CloseTTFont(t); return SF_TTFORMAT; } int i; @@ -1460,24 +1498,28 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) } else if (TTCTag == T_otto) { /* PS-OpenType font */ tdoffset = 0; } else if (TTCTag == T_ttcf) { /* TrueType collection */ + if (!withinBounds(12, 4 * facenum, sizeof(sal_uInt32), t->fsize)) { + return SF_FONTNO; + } sal_uInt32 Version = GetUInt32(t->ptr, 4); if (Version != 0x00010000 && Version != 0x00020000) { - CloseTTFont(t); return SF_TTFORMAT; } if (facenum >= GetUInt32(t->ptr, 8)) { - CloseTTFont(t); return SF_FONTNO; } tdoffset = GetUInt32(t->ptr, 12 + 4 * facenum); } else { - CloseTTFont(t); return SF_TTFORMAT; } - t->ntables = GetUInt16(t->ptr + tdoffset, 4); - if( t->ntables >= 128 ) + if (withinBounds(tdoffset, 0, 4 + sizeof(sal_uInt16), t->fsize)) { + t->ntables = GetUInt16(t->ptr + tdoffset, 4); + } + + if (t->ntables >= 128 || t->ntables == 0) { return SF_TTFORMAT; + } t->tables = static_cast<const sal_uInt8**>(calloc(NUM_TAGS, sizeof(sal_uInt8 *))); assert(t->tables != nullptr); @@ -1489,7 +1531,7 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) int nIndex; const sal_uInt32 nStart = tdoffset + 12; const sal_uInt32 nOffset = 16 * i; - if (nStart + nOffset + sizeof(sal_uInt32) <= static_cast<sal_uInt32>(t->fsize)) + if (withinBounds(nStart, nOffset, sizeof(sal_uInt32), t->fsize)) tag = GetUInt32(t->ptr + nStart, nOffset); else tag = static_cast<sal_uInt32>(-1); @@ -1513,9 +1555,10 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) case T_CFF: nIndex = O_CFF; break; default: nIndex = -1; break; } - if( nIndex >= 0 ) { - sal_uInt32 nTableOffset = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 8); - length = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 12); + + if ((nIndex >= 0) && withinBounds(nStart, nOffset, 12 + sizeof(sal_uInt32), t->fsize)) { + sal_uInt32 nTableOffset = GetUInt32(t->ptr + nStart, nOffset + 8); + length = GetUInt32(t->ptr + nStart, nOffset + 12); t->tables[nIndex] = t->ptr + nTableOffset; t->tlens[nIndex] = length; } @@ -1524,8 +1567,9 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) /* Fixup offsets when only a TTC extract was provided */ if( facenum == (sal_uInt32)~0 ) { sal_uInt8* pHead = const_cast<sal_uInt8*>(t->tables[O_head]); - if( !pHead ) + if (!pHead) { return SF_TTFORMAT; + } /* limit Head candidate to TTC extract's limits */ if( pHead > t->ptr + (t->fsize - 54) ) pHead = t->ptr + (t->fsize - 54); @@ -1541,8 +1585,9 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) break; } } - if( p <= t->ptr ) + if (p <= t->ptr) { return SF_TTFORMAT; + } } /* Check the table offsets after TTC correction */ @@ -1564,7 +1609,7 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) } else if( const_cast<sal_uInt8*>(t->tables[i]) + t->tlens[i] > t->ptr + t->fsize ) { - int nMaxLen = (t->ptr + t->fsize) - t->tables[i]; + sal_PtrDiff nMaxLen = (t->ptr + t->fsize) - t->tables[i]; if( nMaxLen < 0 ) nMaxLen = 0; t->tlens[i] = nMaxLen; @@ -1582,7 +1627,6 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) */ if( !(getTable(t, O_maxp) && getTable(t, O_head) && getTable(t, O_name) && getTable(t, O_cmap)) ) { - CloseTTFont(t); return SF_TTFORMAT; } @@ -1593,14 +1637,12 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) table = getTable(t, O_head); table_size = getTableSize(t, O_head); if (table_size < 52) { - CloseTTFont(t); return SF_TTFORMAT; } t->unitsPerEm = GetUInt16(table, 18); int indexfmt = GetInt16(table, 50); if( ((indexfmt != 0) && (indexfmt != 1)) || (t->unitsPerEm <= 0) ) { - CloseTTFont(t); return SF_TTFORMAT; } @@ -1624,7 +1666,6 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) /* TODO: implement to get subsetting */ assert(t->goffsets != nullptr); } else { - CloseTTFont(t); return SF_TTFORMAT; } @@ -1639,6 +1680,8 @@ static int doOpenTTFont( sal_uInt32 facenum, TrueTypeFont* t ) GetNames(t); FindCmap(t); + aCloseGuard.clear(); + return SF_OK; } @@ -2403,14 +2446,18 @@ void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info) } table = getTable(ttf, O_head); /* 'head' tables is always there */ - info->xMin = XUnits(UPEm, GetInt16(table, 36)); - info->yMin = XUnits(UPEm, GetInt16(table, 38)); - info->xMax = XUnits(UPEm, GetInt16(table, 40)); - info->yMax = XUnits(UPEm, GetInt16(table, 42)); - info->macStyle = GetInt16(table, 44); + table_size = getTableSize(ttf, O_head); + if (table_size >= 46) { + info->xMin = XUnits(UPEm, GetInt16(table, 36)); + info->yMin = XUnits(UPEm, GetInt16(table, 38)); + info->xMax = XUnits(UPEm, GetInt16(table, 40)); + info->yMax = XUnits(UPEm, GetInt16(table, 42)); + info->macStyle = GetInt16(table, 44); + } table = getTable(ttf, O_hhea); - if (table) { + table_size = getTableSize(ttf, O_hhea); + if (table && table_size >= 10) { info->ascender = XUnits(UPEm, GetInt16(table, 4)); info->descender = XUnits(UPEm, GetInt16(table, 6)); info->linegap = XUnits(UPEm, GetInt16(table, 8)); |