summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2018-02-07 17:17:14 +0000
committerMichael Stahl <mstahl@redhat.com>2018-02-09 18:04:31 +0100
commitb45973d30740a7103f32f731a37554736308c6ed (patch)
treee317285d5dcad529c996227203f90899df74f662 /vcl
parent1e9c954ffb1bca7f07509331802dd4ac85a7b11b (diff)
various sft fixes
use ptr diff rather than int (cherry picked from commit 5b426038a7befcaf0d05824ffb20200ff8833ad3) fix mem leak (cherry picked from commit 603cb6cf31a5212d03736a552770e5734b0e8066) check more table sizes (cherry picked from commit 1828490bb22f1c8273c4a9f5b1db819b173ca70d) check cmap offset (cherry picked from commit 683d9883ad8fd6568e6a7832e5bb347c1d043e4b) check tableoffset against size (cherry picked from commit ae73c3ff112e1ed38eb4678ac5745990661a2e66) check ntables offset (cherry picked from commit 75a171a405afd6eac236af93aa9d29a9c3ec9c64) use safeint on calculations (cherry picked from commit 139b6c6cf898467098f3a6f29fa84013a182285f) simplify returns (cherry picked from commit e8b2aad1cb2107304761e68aa380b5c29d8ef22f) extend to cover the last byte needed (cherry picked from commit c7b0117f26a386c98a721ff3897479c268103d74) bounds check (cherry picked from commit bb32616bdd6e3b327654bab0e1d790d8d50b893d) move largest bounds check to start (cherry picked from commit f832198e6a33052c7cc86b25843badfb962a2ae8) Change-Id: Ia174fd94c57cc3c899c10e1c0dc5968965a50427 0d329357ac282d4652b0f7ebc401cbd51963461b 004a6d322f60d916cc4635b362ce948e8a10d7c7 5aae26c38f3645020f0e1d6d7b6877c2727af1b4 a79be052dd3f6b6ed38fb326558924c853af5fff d75f5f4b578fd176c17e5763569f1403260c6594 c063786ba41aa9a985f505e62b43d3d543a0d48f 1a67cb2f1c686032438852fec1267a59fbd04d7f 5177d42b47a4bca614878dce4a69ab16b5cfe163 6d32a6b6f1dd91db42a3f154700ea55603f0e4dd 03fe80f9568759b829fac4e9bcfd496efebe6a26 Reviewed-on: https://gerrit.libreoffice.org/49484 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Michael Stahl <mstahl@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/source/fontsubset/sft.cxx95
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));