Bug 487549. Do kern table sanity checks on downloaded fonts. r=roc

This commit is contained in:
Jonathan Kew 2009-04-14 17:48:32 +09:00
Родитель d5b82c2056
Коммит 84c9c97447
4 изменённых файлов: 104 добавлений и 2 удалений

Просмотреть файл

@ -0,0 +1,23 @@
<html>
<head>
<title>Bad kern table - bug 487549</title>
<!--
The font used here has an invalid 'kern' table that will crash ATSUI
if we attempt to use it.
See https://bugzilla.mozilla.org/show_bug.cgi?id=487549
-->
<style>
@font-face {
font-family: bad-kern-font;
src: url(487549-bad_kern_table.ttf) format("truetype");
}
body {
font-family: bad-kern-font;
}
</style>
</head>
<body>
ABC abc 123
</body>
</html>

Двоичные данные
gfx/thebes/crashtests/487549-bad_kern_table.ttf Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -50,3 +50,4 @@ load 463307-1.html
load 467873-1.html load 467873-1.html
load 470418-1.html load 470418-1.html
skip-if(MOZ_WIDGET_TOOLKIT=="gtk2") load 441360.html # filed bug 455463 for gtk2 skip-if(MOZ_WIDGET_TOOLKIT=="gtk2") load 441360.html # filed bug 455463 for gtk2
load 487549-1.html

Просмотреть файл

@ -654,6 +654,32 @@ struct OS2Table {
AutoSwap_PRUint16 usMaxContext; AutoSwap_PRUint16 usMaxContext;
}; };
// old 'kern' table, supported on Windows
// see http://www.microsoft.com/typography/otspec/kern.htm
struct KernTableVersion0 {
AutoSwap_PRUint16 version; // 0x0000
AutoSwap_PRUint16 nTables;
};
struct KernTableSubtableHeaderVersion0 {
AutoSwap_PRUint16 version;
AutoSwap_PRUint16 length;
AutoSwap_PRUint16 coverage;
};
// newer Mac-only 'kern' table, ignored by Windows
// see http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6kern.html
struct KernTableVersion1 {
AutoSwap_PRUint32 version; // 0x00010000
AutoSwap_PRUint32 nTables;
};
struct KernTableSubtableHeaderVersion1 {
AutoSwap_PRUint32 length;
AutoSwap_PRUint16 coverage;
AutoSwap_PRUint16 tupleIndex;
};
static PRBool static PRBool
IsValidSFNTVersion(PRUint32 version) IsValidSFNTVersion(PRUint32 version)
{ {
@ -675,6 +701,44 @@ CopySwapUTF16(const PRUint16 *aInBuf, PRUint16 *aOutBuf, PRUint32 aLen)
} }
} }
static PRBool
ValidateKernTable(const PRUint8 *aKernTable, PRUint32 aKernLength)
{
// -- kern table can cause crashes if invalid, so do some basic sanity-checking
const KernTableVersion0 *kernTable0 = reinterpret_cast<const KernTableVersion0*>(aKernTable);
if (aKernLength < sizeof(KernTableVersion0)) {
return PR_FALSE;
}
if (PRUint16(kernTable0->version) == 0) {
if (aKernLength < sizeof(KernTableVersion0) +
PRUint16(kernTable0->nTables) * sizeof(KernTableSubtableHeaderVersion0)) {
return PR_FALSE;
}
// at least the table is big enough to contain the subtable headers;
// we could go further and check the actual subtable sizes....
// for now, assume this is OK
return PR_TRUE;
}
const KernTableVersion1 *kernTable1 = reinterpret_cast<const KernTableVersion1*>(aKernTable);
if (aKernLength < sizeof(KernTableVersion1)) {
return PR_FALSE;
}
if (kernTable1->version == 0x00010000) {
if (aKernLength < sizeof(KernTableVersion1) +
kernTable1->nTables * sizeof(KernTableSubtableHeaderVersion1)) {
return PR_FALSE;
}
// at least the table is big enough to contain the subtable headers;
// we could go further and check the actual subtable sizes....
// for now, assume this is OK
return PR_TRUE;
}
// neither the old Windows version nor the newer Apple one; refuse to use it
return PR_FALSE;
}
PRBool PRBool
gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData, gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
PRUint32 aFontDataLength, PRUint32 aFontDataLength,
@ -702,8 +766,8 @@ gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
// iterate through the table headers to find the head, name and OS/2 tables // iterate through the table headers to find the head, name and OS/2 tables
PRBool foundHead = PR_FALSE, foundOS2 = PR_FALSE, foundName = PR_FALSE; PRBool foundHead = PR_FALSE, foundOS2 = PR_FALSE, foundName = PR_FALSE;
PRBool foundGlyphs = PR_FALSE, foundCFF = PR_FALSE; PRBool foundGlyphs = PR_FALSE, foundCFF = PR_FALSE, foundKern = PR_FALSE;
PRUint32 headOffset, headLen, nameOffset, nameLen; PRUint32 headOffset, headLen, nameOffset, nameLen, kernOffset, kernLen;
PRUint32 i, numTables; PRUint32 i, numTables;
numTables = sfntHeader->numTables; numTables = sfntHeader->numTables;
@ -749,6 +813,12 @@ gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
} }
break; break;
case TRUETYPE_TAG('k','e','r','n'):
foundKern = PR_TRUE;
kernOffset = dirEntry->offset;
kernLen = dirEntry->length;
break;
case TRUETYPE_TAG('n','a','m','e'): case TRUETYPE_TAG('n','a','m','e'):
foundName = PR_TRUE; foundName = PR_TRUE;
nameOffset = dirEntry->offset; nameOffset = dirEntry->offset;
@ -840,6 +910,14 @@ gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
} }
} }
// -- sanity-check the kern table, if present (see bug 487549)
if (foundKern) {
if (!ValidateKernTable(aFontData + kernOffset, kernLen)) {
NS_WARNING("invalid font (kern table)");
return PR_FALSE;
}
}
// everything seems consistent // everything seems consistent
return PR_TRUE; return PR_TRUE;
} }