bug 580212 - loca table validation. r=jdaggett

This commit is contained in:
Jonathan Kew 2010-07-22 10:25:23 +01:00
Родитель b4588f42d5
Коммит fa0ceecdf2
5 изменённых файлов: 88 добавлений и 6 удалений

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

@ -0,0 +1,7 @@
<html><head>
<style>@font-face{font-family:t;src:url(580212-bad_loca_table.ttf);}
p.t{font-size:40px;font-family:t;}</style>
</head>
<body>
<p class="t">Lorem ipsum</p></body>
</html>

Двоичные данные
gfx/tests/crashtests/580212-bad_loca_table.ttf Normal file

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

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

@ -77,3 +77,4 @@ load 538065-1.html
load 546870-1.html
load balinese-letter-spacing.html
load 580100-1.html
load 580212-1.html

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

@ -1024,6 +1024,45 @@ ValidateKernTable(const PRUint8 *aKernTable, PRUint32 aKernLength)
return PR_FALSE;
}
static PRBool
ValidateLocaTable(const PRUint8* aLocaTable, PRUint32 aLocaLen,
PRUint32 aGlyfLen, PRInt16 aLocaFormat, PRUint16 aNumGlyphs)
{
if (aLocaFormat == 0) {
if (aLocaLen < PRUint32(aNumGlyphs + 1) * sizeof(PRUint16)) {
return PR_FALSE;
}
const AutoSwap_PRUint16 *p =
reinterpret_cast<const AutoSwap_PRUint16*>(aLocaTable);
PRUint32 prev = 0;
for (PRUint32 i = 0; i <= aNumGlyphs; ++i) {
PRUint32 current = PRUint16(*p++) * 2;
if (current < prev || current > aGlyfLen) {
return PR_FALSE;
}
prev = current;
}
return PR_TRUE;
}
if (aLocaFormat == 1) {
if (aLocaLen < (aNumGlyphs + 1) * sizeof(PRUint32)) {
return PR_FALSE;
}
const AutoSwap_PRUint32 *p =
reinterpret_cast<const AutoSwap_PRUint32*>(aLocaTable);
PRUint32 prev = 0;
for (PRUint32 i = 0; i <= aNumGlyphs; ++i) {
PRUint32 current = *p++;
if (current < prev || current > aGlyfLen) {
return PR_FALSE;
}
prev = current;
}
return PR_TRUE;
}
return PR_FALSE;
}
gfxUserFontType
gfxFontUtils::DetermineFontDataType(const PRUint8 *aFontData, PRUint32 aFontDataLength)
{
@ -1075,7 +1114,9 @@ gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
// 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 foundGlyphs = PR_FALSE, foundCFF = PR_FALSE, foundKern = PR_FALSE;
PRUint32 headOffset, headLen, nameOffset, nameLen, kernOffset, kernLen;
PRBool foundLoca = PR_FALSE, foundMaxp = PR_FALSE;
PRUint32 headOffset, headLen, nameOffset, nameLen, kernOffset, kernLen,
glyfLen, locaOffset, locaLen, maxpOffset, maxpLen;
PRUint32 i, numTables;
numTables = sfntHeader->numTables;
@ -1139,6 +1180,23 @@ gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
case TRUETYPE_TAG('g','l','y','f'): // TrueType-style quadratic glyph table
foundGlyphs = PR_TRUE;
glyfLen = dirEntry->length;
break;
case TRUETYPE_TAG('l','o','c','a'): // glyph location table
foundLoca = PR_TRUE;
locaOffset = dirEntry->offset;
locaLen = dirEntry->length;
break;
case TRUETYPE_TAG('m','a','x','p'): // max profile
foundMaxp = PR_TRUE;
maxpOffset = dirEntry->offset;
maxpLen = dirEntry->length;
if (maxpLen < sizeof(MaxpTableHeader)) {
NS_WARNING("invalid font (maxp table length)");
return PR_FALSE;
}
break;
case TRUETYPE_TAG('C','F','F',' '): // PS-style cubic glyph table
@ -1153,9 +1211,9 @@ gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
// simple sanity checks
// -- fonts need head, name tables
if (!foundHead || !foundName) {
NS_WARNING("invalid font (missing head/name table)");
// -- fonts need head, name, maxp tables
if (!foundHead || !foundName || !foundMaxp) {
NS_WARNING("invalid font (missing head/name/maxp table)");
return PR_FALSE;
}
@ -1190,8 +1248,18 @@ gfxFontUtils::ValidateSFNTHeaders(const PRUint8 *aFontData,
return PR_FALSE;
}
} else {
if (!foundGlyphs) {
NS_WARNING("invalid font (missing glyf table)");
if (!foundGlyphs || !foundLoca) {
NS_WARNING("invalid font (missing glyf or loca table)");
return PR_FALSE;
}
// sanity-check 'loca' offsets
const MaxpTableHeader *maxpData =
reinterpret_cast<const MaxpTableHeader*>(aFontData + maxpOffset);
if (!ValidateLocaTable(aFontData + locaOffset, locaLen, glyfLen,
headData->indexToLocFormat,
maxpData->numGlyphs)) {
NS_WARNING("invalid font (loca table offsets)");
return PR_FALSE;
}
}

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

@ -465,6 +465,12 @@ struct HheaTable {
AutoSwap_PRUint16 numOfLongHorMetrics;
};
struct MaxpTableHeader {
AutoSwap_PRUint32 version; // CFF: 0x00005000; TrueType: 0x00010000
AutoSwap_PRUint16 numGlyphs;
// truetype version has additional fields that we don't currently use
};
#pragma pack()
// Return just the highest bit of the given value, i.e., the highest